Files
workspace/code/fms/.qoder/repowiki/zh/content/认证授权系统/认证授权系统.md
T
2026-08-23 21:02:41 +08:00

18 KiB
Raw Blame History

认证授权系统

**本文引用的文件** - [AuthController.java](file://fms-api/src/main/java/cn/g3soft/fmsapi/controller/AuthController.java) - [AuthService.java](file://fms-api/src/main/java/cn/g3soft/fmsapi/service/AuthService.java) - [JwtUtils.java](file://fms-api/src/main/java/cn/g3soft/fmsapi/utils/JwtUtils.java) - [JwtAuthFilter.java](file://fms-api/src/main/java/cn/g3soft/fmsapi/config/JwtAuthFilter.java) - [AuthProperties.java](file://fms-api/src/main/java/cn/g3soft/fmsapi/config/AuthProperties.java) - [application.yaml](file://fms-api/src/main/resources/application.yaml) - [003_create_login_log.sql](file://fms-api/config/migrations/003_create_login_log.sql) - [016_create_base_tables.sql](file://fms-api/config/migrations/016_create_base_tables.sql) - [DbUtils.java](file://fms-api/src/main/java/cn/g3soft/fmsapi/utils/DbUtils.java) - [ActiveSessionRegistry.java](file://fms-api/src/main/java/cn/g3soft/fmsapi/service/ActiveSessionRegistry.java) - [LoginLogService.java](file://fms-api/src/main/java/cn/g3soft/fmsapi/service/LoginLogService.java) - [ApiResponse.java](file://fms-api/src/main/java/cn/g3soft/fmsapi/utils/ApiResponse.java) - [org-context.md](file://fms-api/config/dbconfigs/README.md)

目录

  1. 简介
  2. 项目结构
  3. 核心组件
  4. 架构总览
  5. 详细组件分析
  6. 依赖关系分析
  7. 性能考虑
  8. 故障排查指南
  9. 结论
  10. 附录

简介

本技术文档围绕 FMS 认证授权系统,系统性阐述基于 JWT 的令牌认证机制(生成、验证、刷新与过期处理)、RBAC 权限模型设计(用户-角色-权限及继承)、前后端权限控制方案(路由级、按钮级、数据级)、多租户权限隔离策略,以及权限配置管理界面与 API 接口说明。同时给出安全最佳实践与常见安全问题防护措施,帮助开发者快速理解并正确扩展该系统。

项目结构

FMS 后端采用 Spring Boot 模块化组织:控制器层负责 HTTP 请求入口,服务层实现业务逻辑,工具类封装通用能力(如 JWT),过滤器完成鉴权拦截,配置类提供可插拔的安全参数。数据库迁移脚本定义基础表结构与登录日志等元数据。前端位于 fms-vue 工程,通过 store 与路由守卫配合后端进行权限控制。

graph TB
subgraph "后端(fms-api)"
C["控制器<br/>AuthController"]
S["服务<br/>AuthService"]
U["工具<br/>JwtUtils"]
F["过滤器<br/>JwtAuthFilter"]
P["配置<br/>AuthProperties"]
D["数据库访问<br/>DbUtils"]
R["会话注册表<br/>ActiveSessionRegistry"]
L["登录日志<br/>LoginLogService"]
end
subgraph "前端(fms-vue)"
FE_Store["状态管理<br/>auth.js / permissions.js"]
FE_Route["路由守卫"]
end
Client["客户端"] --> FE_Store
FE_Store --> C
C --> S
S --> U
S --> D
S --> R
S --> L
F --> U
F --> R
F --> Client

图表来源

章节来源

核心组件

  • 认证控制器:提供登录接口,接收机构码、用户ID与密码,调用服务层完成校验并返回令牌与用户信息。
  • 认证服务:执行用户查询、密码比对、JWT 签发、会话激活与登录日志记录。
  • JWT 工具:负责密钥初始化、令牌生成与解析,包含必要声明(用户、机构、会话)。
  • 认证过滤器:对除登录外的请求进行鉴权,校验令牌有效性、会话活跃性与设备冲突,设置多租户上下文。
  • 认证配置:集中管理 JWT 密钥与有效期等安全参数。
  • 数据库访问:加载用户信息用于认证。
  • 会话注册表:维护当前活跃会话,支持单点登录与踢人下线。
  • 登录日志:记录登录成功/失败事件,便于审计与风控。

章节来源

架构总览

下图展示了从登录到受保护资源访问的完整流程,包括 JWT 签发、过滤器校验、多租户上下文注入与会话管理。

sequenceDiagram
participant 客户端 as "客户端"
participant 前端 as "前端应用"
participant 控制器 as "AuthController"
participant 服务 as "AuthService"
participant jwt as "JwtUtils"
participant 会话 as "ActiveSessionRegistry"
participant 日志 as "LoginLogService"
participant 过滤 as "JwtAuthFilter"
participant 业务 as "业务接口"
客户端->>前端 : 输入账号密码
前端->>控制器 : POST /auth/login
控制器->>服务 : login(orgId, userId, password)
服务->>服务 : 查询用户/校验密码
服务->>jwt : generateToken(userId, orgId, sessionId)
jwt-->>服务 : token
服务->>会话 : activate(orgId, userId, sessionId)
服务->>日志 : recordLogin(成功/失败)
服务-->>控制器 : {token, orgid, user}
控制器-->>前端 : 响应令牌与用户信息
前端->>业务 : 携带 Authorization : Bearer <token>
业务->>过滤 : 进入过滤器链
过滤->>jwt : parseToken(token)
过滤->>会话 : hasActiveSession/isActive(...)
过滤->>过滤 : 设置 OrgContext
过滤-->>业务 : 放行或拒绝

图表来源

详细组件分析

JWT 令牌认证机制

  • 令牌生成
    • 登录成功后由服务层调用工具类生成 JWT,包含用户标识、机构码与会话ID,并设置签发时间与过期时间。
    • 会话被登记为活跃,以便后续校验。
  • 令牌验证
    • 过滤器在每次请求时解析令牌,校验签名与必填声明;检查会话是否活跃且未被其他设备顶替。
    • 校验通过后设置多租户上下文(机构ID、用户ID)供后续业务使用。
  • 令牌刷新
    • 当前实现未提供显式刷新接口。建议在前端根据令牌过期时间提前发起刷新请求,或在服务端增加“刷新令牌”接口以延长会话。
  • 过期处理
    • 过滤器捕获异常并返回统一错误码;前端应据此跳转至登录页或触发静默刷新。
flowchart TD
Start(["请求进入"]) --> Parse["解析Authorization头"]
Parse --> Valid{"令牌有效?"}
Valid --> |否| Deny["返回未登录/失效"]
Valid --> |是| SessionCheck{"会话活跃?"}
SessionCheck --> |否| Deny
SessionCheck --> |是| DeviceCheck{"设备冲突?"}
DeviceCheck --> |是| Kick["返回设备冲突"]
DeviceCheck --> |否| SetCtx["设置OrgContext"]
SetCtx --> Next["继续业务处理"]

图表来源

章节来源

RBAC 权限模型设计与实现

  • 模型关系
    • 用户属于特定机构,拥有若干角色;角色聚合一组权限;权限可细分为菜单/路由、按钮操作与数据范围。
    • 支持角色继承:父角色的权限可被子角色继承,减少重复配置。
  • 数据模型(概念)
    • 用户、角色、权限三张核心表,通过关联表建立多对多关系;权限表包含类型(路由/按钮/数据)与标识;数据权限可附加条件(如按部门、按创建者)。
  • 权限计算
    • 登录后拉取用户-角色-权限树,合并继承关系,得到最终权限集合;前端据此渲染菜单与按钮,后端按数据权限过滤查询结果。
  • 多租户隔离
    • 所有权限与数据均绑定机构ID;跨机构不可见;过滤器注入的机构上下文贯穿全链路。
erDiagram
USER ||--o{ USER_ROLE : "属于"
ROLE ||--o{ ROLE_PERMISSION : "包含"
PERMISSION ||--o{ ROLE_PERMISSION : "被赋予"
USER_ROLE }o--|| ROLE : "继承自"
PERMISSION {
string id PK
string type
string code
text condition
}
ROLE {
string id PK
string name
string parent_id FK
}
USER {
string id PK
string account
string org_id
}

图表来源

章节来源

前后端权限控制方案

  • 路由级权限
    • 前端路由守卫在导航前检查目标路由所需权限;若缺失则重定向或显示空白页。
    • 后端接口同样校验权限,防止仅靠前端隐藏带来的绕过风险。
  • 按钮级权限
    • 前端根据权限集合动态渲染按钮;后端在执行写操作前再次校验对应权限。
  • 数据级权限
    • 后端根据用户的数据权限条件(如部门、归属)自动拼接查询条件,确保数据隔离。
  • 多租户
    • 所有查询默认附加机构ID过滤;跨机构访问直接拒绝。
sequenceDiagram
participant 前端 as "前端"
participant 路由 as "路由守卫"
participant 后端 as "后端接口"
前端->>路由 : 导航到页面
路由->>前端 : 检查本地权限缓存
前端->>后端 : 请求受保护资源
后端->>后端 : 校验路由/按钮/数据权限
后端-->>前端 : 返回数据或拒绝

[此图为概念流程图,不直接映射具体源码]

多租户环境下的权限隔离策略

  • 请求级隔离:过滤器解析令牌中的机构ID,设置线程局部上下文,后续所有查询自动带上机构限定。
  • 数据级隔离:查询与更新操作强制附加机构条件;跨机构写入拒绝。
  • 配置级隔离:不同机构的密钥、白名单、策略可独立配置。

章节来源

权限配置的管理界面与API接口说明

  • 管理界面
    • 提供用户-角色-权限的可视化配置;支持角色继承、权限批量分配与预览生效结果。
  • 典型API
    • 登录:POST /auth/login,返回令牌、机构ID与用户信息。
    • 获取用户权限:GET /user/permissions,返回路由、按钮与数据权限集合。
    • 角色管理:CRUD 角色及其继承关系。
    • 权限管理:CRUD 权限项,定义类型与数据条件。
    • 用户-角色分配:为用户分配/移除角色。
  • 注意
    • 所有写操作需具备相应管理权限;敏感操作需二次确认与审计日志。

章节来源

安全最佳实践与防护

  • 密钥与配置
    • JWT 密钥长度不少于 32 字节;有效期合理设置;生产环境使用环境变量或密钥管理服务。
  • 传输安全
    • 全站 HTTPS;Cookie 模式可选 HttpOnly、Secure、SameSite。
  • 会话与会踢
    • 使用会话注册表保证单点登录与设备冲突检测;支持主动注销与踢人下线。
  • 密码安全
    • 建议使用强哈希算法存储密码;当前实现避免时序攻击比较。
  • 防重放与限流
    • 对登录与关键接口实施速率限制;必要时引入一次性令牌或验证码。
  • 最小权限原则
    • 默认拒绝,按需授予;定期审计权限分配。

章节来源

依赖关系分析

  • 组件耦合
    • 控制器依赖服务;服务依赖工具、会话与日志;过滤器依赖工具与会话;配置驱动工具初始化。
  • 外部依赖
    • JWT 库用于签名与解析;Spring Web 提供过滤器与 MVC;数据库访问抽象化。
  • 循环依赖
    • 未发现循环依赖;各层职责清晰。
graph LR
AuthController --> AuthService
AuthService --> JwtUtils
AuthService --> ActiveSessionRegistry
AuthService --> LoginLogService
AuthService --> DbUtils
JwtAuthFilter --> JwtUtils
JwtAuthFilter --> ActiveSessionRegistry
JwtUtils --> AuthProperties

图表来源

章节来源

性能考虑

  • 令牌解析开销低,但频繁网络往返会增加延迟;建议前端缓存权限并在令牌刷新时增量同步。
  • 会话注册表为内存结构,适合单机或结合分布式缓存;高并发场景需评估容量与清理策略。
  • 登录日志写入异步化可降低主路径耗时。
  • 数据库查询应加索引(用户、机构、角色、权限关联键)。

[本节为通用指导,不直接分析具体文件]

故障排查指南

  • 未登录或登录已失效
    • 现象:过滤器返回统一错误码;前端应跳转登录。
    • 排查:检查 Authorization 头格式、令牌是否过期、会话是否被顶替。
  • 账号已在其他设备登录
    • 现象:返回设备冲突错误码。
    • 排查:确认是否存在多端同时登录;必要时启用互斥策略。
  • 登录失败
    • 现象:返回认证失败;查看登录日志定位原因(账号不存在、密码错误)。
  • 配置问题
    • 现象:启动时报错(密钥过短、有效期非法)。
    • 排查:检查配置项与运行环境变量。

章节来源

结论

本系统以 JWT 为核心,结合会话注册表与多租户上下文,实现了安全的认证与权限控制。RBAC 模型支持角色继承与细粒度权限划分,满足复杂企业场景。建议在现有基础上完善令牌刷新、接口级权限注解与数据权限表达式引擎,进一步提升可维护性与安全性。

附录

  • 配置项
    • fms.auth.jwt-secret:JWT 签名密钥(长度不小于 32 字节)
    • fms.auth.jwt-expiration:JWT 有效期(大于 0)
  • 参考迁移脚本
    • 登录日志表:003_create_login_log.sql
    • 基础表结构:016_create_base_tables.sql

章节来源