🔒 safe-vitepress — 带身份认证的 VitePress 文档站
"文档站也能有登录,公开页面随便看,受保护页面要登录。"
概述
safe-vitepress 是一个参考演示项目,展示如何将 VitePress 静态文档站点与 FastAPI 后端结合,实现基于 JWT 的身份认证和角色权限控制。核心理念:部分文档页面公开访问,部分需要用户登录后才能查看。VitePress 前端检测每个页面的 protected frontmatter 标记,对未认证用户显示登录弹窗。
GitHub: https://github.com/mikigo/safe-vitepress
解决的痛点
- 内部文档需要权限控制,但 VitePress 是纯静态站点,没有内置认证机制
- 希望部分页面全员可看,部分页面仅登录用户可看
- 需要一个轻量级的认证方案,不需要复杂的全栈框架
- 作为参考实现,演示 VitePress + FastAPI 结合的最佳实践
核心流程
核心特性
页面级访问控制
每篇 Markdown 页面通过 frontmatter 声明是否需要保护:
前端认证组件
自定义的 VitePress 主题注入了三个组件到导航栏 #nav-bar-content-before 插槽:
AuthGuard 守卫组件
AuthGuard.vue 包裹整个布局,在挂载时尝试获取当前用户信息。渲染页面时检查 frontmatter.protected:
- 为
true且未认证 → 显示登录提示,隐藏页面内容 - 为
false→ 直接渲染页面
JWT 认证
后端使用 OAuth2 密码流签发 JWT Token(HS256),有效期 30 分钟。Token 存储在前端 localStorage,Axios 拦截器自动为所有请求附加 Authorization: Bearer <token> 头。
角色控制
用户模型包含 is_admin 字段,创建新用户需要 admin 权限。
前端状态管理
通过 Vue composable useAuth() 管理认证状态,使用 @vueuse/core 的 useStorage 将 token 持久化到 localStorage。页面刷新后自动恢复登录态。
技术栈
项目结构
后端 API
数据模型
效果展示
受保护页面需要登录:

登录弹窗:

登录成功:

用户信息和登出:

使用方式
环境要求
- Python 3.10+
- Node.js 18+
- pnpm
后端启动
创建管理员
交互式输入用户名和密码,直接通过 Tortoise-ORM 写入数据库,is_admin=True。
前端启动
页面保护配置
在任意 .md 文件的 frontmatter 中添加:
配置项
部署
.github/workflows/deploy.yml:推送 main 分支自动构建 VitePress 并部署到 GitHub Pages。注意后端需要单独部署,GitHub Pages 仅托管前端静态文件。
设计说明
- 演示项目:这是一个参考实现,展示了 VitePress + FastAPI 结合的最佳实践,安全密钥使用占位符,CORS 全开放,适合作为学习或定制起点
- 认证状态持久化:token 存储在 localStorage,刷新页面自动恢复登录状态
- VitePress 主题扩展:通过
#nav-bar-content-before插槽注入认证组件,不破坏默认主题结构
许可证
Apache 2.0