从零分析一个个人 SSO 权限管理系统
从零分析一个个人 SSO 权限管理系统
这组文章基于一个面向个人多项目使用的 SSO 权限管理系统展开。项目不是只做登录页,而是把 OAuth2 / OIDC、应用接入、用户组、角色、权限、安全策略、审计日志和 demo 接入示例都放进了一个完整闭环里。
项目技术栈:
- 后端:Node.js、Fastify、Prisma、SQLite、jose
- 前端:Vue 3、Vite、Pinia、Tailwind CSS、lucide-vue-next
- 协议:OAuth2 授权码模式、OIDC Discovery、JWKS、PKCE、Refresh Token Rotation
- 示例业务系统:Vue 前端 + Fastify API
文章结构
- 01-backend.md:后端架构、认证授权、权限模型、OAuth/OIDC 流程、数据模型和安全设计。
- 02-frontend.md:管理后台结构、登录态维护、路由守卫、权限视图、表单编辑和交互设计。
- 03-integration-deployment.md:业务系统如何接入、demo 实现、部署策略和后续演进方向。
如果只想快速了解项目,可以先看本文。想复盘实现细节,再分别阅读后端篇和前端篇。
项目定位
这个项目的目标不是替代企业级身份平台,而是解决个人或轻量团队在多个项目之间反复造登录、权限和用户管理的问题。
它覆盖的核心需求包括:
- 多个业务系统统一登录。
- 业务系统通过标准 OAuth/OIDC 流程接入。
- 在一个后台里管理用户、用户组、角色和权限。
- 通过应用前缀限制应用管理员的管理范围。
- 支持登录日志、审计日志、安全策略、会话管理和 SQLite 自动备份。
- 提供一个 demo 项目说明业务系统该如何校验 token 和判断权限。
项目当前更适合单实例、小流量、个人生产环境。它默认使用 SQLite,并通过 WAL、busy timeout 和每日备份增强可靠性。如果未来需要多实例、高并发或团队级运维,数据库和密钥管理需要进一步升级。
目录结构
.├── backend/ # Fastify + Prisma 后端├── frontend/ # Vue 3 + Tailwind 管理后台├── demo/ # 接入 SSO 的业务系统示例├── docs/ # 文档站点和设计文档├── todo/ # 后续优化记录├── package.json # npm workspace 入口└── README.md根目录使用 npm workspace 管理三个子项目:backend、frontend、demo。常用命令集中在根 package.json:
npm run dev # 同时启动后端和管理后台npm run dev:all # 同时启动后端、管理后台和 demonpm run build # 构建管理后台npm run db:push # 同步 Prisma schemanpm run db:seed # 初始化基础数据npm test # 运行后端测试核心模块
系统可以按四个层次理解:
| 层次 | 说明 |
|---|---|
| 身份认证 | 用户名密码登录、验证码、会话、access token、refresh token、退出登录。 |
| OAuth/OIDC | 授权码模式、PKCE、Discovery、JWKS、UserInfo、Introspection、Revoke、Logout。 |
| 权限管理 | 用户、用户组、角色、权限,以及用户/用户组直接授权和角色授权。 |
| 运维安全 | 安全策略、CORS 白名单、审计日志、登录日志、签名密钥轮换、SQLite 备份。 |
后端负责协议、安全和数据一致性;前端负责把这些能力组织成可管理的后台;demo 用最小业务系统展示接入方式。
权限模型
项目使用点号分层权限:
adminsso.adminsso.user.admindemo-app.userdemo-app.admindemo-app.order.read规则很直接:
admin拥有全部权限。sso.admin拥有 SSO 平台权限。{app}.admin拥有某个业务应用下的管理权限。- 普通权限必须精确匹配。
- 如果某一级是
admin,则覆盖该级以下所有权限,例如sso.user.admin覆盖sso.user.read和sso.user.write。
用户最终权限来自四个来源:
用户最终权限 = 用户直接权限 + 用户直接角色权限 + 所属用户组直接权限 + 所属用户组角色权限这种模型的好处是容易理解,也容易在业务系统里复刻判断逻辑。demo API 就复用了同样的 permissionImplies 规则来判断当前用户是否能访问接口。
OAuth/OIDC 登录闭环
业务系统接入时走标准授权码流程:
业务系统生成 state 和 PKCE verifier/challenge ↓跳转到 /oauth/authorize ↓SSO 校验 client、redirect_uri、scope、audience、PKCE ↓用户登录或复用 SSO session ↓需要时进入 consent 授权确认页 ↓SSO 生成 authorization code 并跳回业务系统 ↓业务系统调用 /oauth/token 换取 token ↓业务 API 使用 JWKS 校验 access token项目实现了几个关键安全点:
redirect_uri必须和 client 配置精确匹配。- public client 必须使用 PKCE。
- confidential client 必须校验 client secret。
- authorization code 只能使用一次。
- refresh token 每次使用都会轮换,旧 token 复用时撤销整个 token family。
- access token 带有
jti,退出或 revoke 后可以进入黑名单。 - token 中包含
permission_version,权限变更后旧 token 会失效。
数据模型概览
Prisma schema 中的主要模型如下:
| 模型 | 作用 |
|---|---|
User | 用户账号、密码哈希、状态、权限版本、登录状态字段。 |
Group | 用户组。 |
Role | 角色,可绑定应用。 |
Permission | 权限字典,可绑定应用。 |
OAuthClient | 接入 SSO 的业务系统配置。 |
Session | 用户登录会话。 |
RefreshToken | refresh token 记录和 token family 状态。 |
AuthorizationCode | 授权码记录。 |
TokenBlacklist | 被撤销的 access token jti。 |
AuditLog | 管理操作审计日志。 |
LoginLog | 登录日志。 |
SecurityPolicy | 密码、验证码、token TTL、CORS 策略。 |
KeyPair | JWT 签名密钥。 |
UserConsent | 用户对第三方 client 的授权记录。 |
从模型可以看出,这个系统不是只在 JWT 里塞权限,而是有完整的持久化状态。会话、refresh token、授权码、黑名单和权限版本共同构成了 token 生命周期管理。
前端管理后台
管理后台采用 Vue 3 单页应用,页面包括:
- 概览
- 个人中心
- 会话
- 用户
- 用户组
- 角色
- 权限
- 应用接入
- 审计日志
- 安全策略
它的关键设计不是页面数量,而是权限范围感知:
- 平台管理员可以看到全部菜单。
- 应用管理员只能看到和应用内管理相关的页面。
- 普通用户只看到个人中心和会话。
- 用户、用户组、角色、权限页面会按应用范围加载数据。
前端的登录态存储在 Pinia 和 localStorage 中。Axios 拦截器会自动携带 Bearer token,并在 401 时尝试使用 refresh token 静默刷新。刷新成功后通过浏览器事件同步 Pinia 状态;刷新失败则清理本地状态并跳回登录页。
应用创建时的自动初始化
创建 OAuth client 时,后端不仅保存 client 配置,还会自动创建:
{clientKey}.admin权限{clientKey}.user权限{clientKey}.admin内置管理员角色{clientKey}.user内置用户角色{clientKey}-admin默认应用管理员用户
这个设计让新应用接入后立即具备最小可管理闭环。平台管理员不用手动创建一堆基础权限和角色,应用管理员也能基于 {app}.admin 管理自己应用范围内的资源。
项目的取舍
这个项目的取舍比较清晰:
- 选择 SQLite 降低部署成本,但限制多实例和高并发写入。
- 使用标准 OAuth/OIDC 端点降低业务系统接入成本。
- 使用点号层级权限而不是复杂 ABAC,降低理解和维护成本。
- 用 refresh token rotation 和 token blacklist 弥补 JWT 天然无状态带来的撤销问题。
- 把应用管理员范围做在后端
accessScope中,而不是只依赖前端隐藏菜单。
这类取舍适合个人项目。它不是最强的身份系统,但它覆盖了日常项目最容易遗漏的安全与管理细节。
阅读建议
如果你准备复用这个项目,可以按下面顺序读代码【代码暂未开源,敬请期待】:
backend/prisma/schema.prisma:先理解数据模型。backend/src/server.js:理解 Fastify 插件、路由注册和后台任务。backend/src/services/tokenService.js:理解 token 签发。backend/src/services/oauthService.js:理解 OAuth/OIDC 主流程。backend/src/authorization.js和backend/src/accessScope.js:理解权限计算和管理范围。frontend/src/stores/authStore.js、frontend/src/services/api.js、frontend/src/router/index.js:理解前端登录态和权限路由。demo/src/auth.js和demo/server/index.js:理解业务系统如何接入。
下面进入后端篇。
个人 SSO 权限系统
记录我为个人多项目搭建统一登录和权限管理系统的完整过程,覆盖架构、OAuth、安全闭环、权限模型、接入和部署。
March7th