Files
workspace/code/fms/.qoder/repowiki/zh/content/后端架构/安全认证.md
T
2026-08-23 21:02:41 +08:00

14 KiB
Raw Blame History

安全认证

**本文引用的文件** - [AuthProperties.java](file://fms-api/src/main/java/cn/g3soft/fmsapi/config/AuthProperties.java) - [JwtAuthFilter.java](file://fms-api/src/main/java/cn/g3soft/fmsapi/config/JwtAuthFilter.java) - [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) - [AuthenticationException.java](file://fms-api/src/main/java/cn/g3soft/fmsapi/exception/AuthenticationException.java) - [JwtUtilsTests.java](file://fms-api/src/test/java/cn/g3soft/fmsapi/utils/JwtUtilsTests.java)

目录

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

简介

本文件面向FMS后端的安全认证子系统,聚焦基于JWT的无状态认证方案。文档围绕以下目标展开:

  • 解释JwtAuthFilter过滤器的工作流程与拦截策略
  • 说明令牌生成、校验与刷新机制
  • 阐述AuthProperties配置类与安全参数管理
  • 描述JwtUtils工具类的核心能力(解析、用户信息提取、权限验证)
  • 给出过期处理、防重放攻击等安全考量与最佳实践

项目结构

安全认证相关代码集中在fms-api模块中,采用分层组织:

  • 配置层:AuthProperties负责读取并绑定安全相关配置项
  • 过滤层:JwtAuthFilter在请求进入控制器前进行鉴权
  • 控制层:AuthController暴露登录、登出、刷新等接口
  • 服务层:AuthService封装认证业务逻辑(如会话管理、权限加载)
  • 异常层:AuthenticationException统一认证失败异常
  • 工具层:JwtUtils提供JWT编解码与校验能力(通过测试用例可见其使用方式)
graph TB
Client["客户端"] --> Filter["JwtAuthFilter<br/>请求前置鉴权"]
Filter --> Controller["AuthController<br/>登录/刷新/登出"]
Controller --> Service["AuthService<br/>认证业务逻辑"]
Service --> Utils["JwtUtils<br/>令牌解析/校验"]
Service --> Config["AuthProperties<br/>安全参数配置"]
Service --> DB["数据源/缓存<br/>用户与权限"]

图表来源

章节来源

核心组件

  • JwtAuthFilter:在Servlet过滤器链中对每个请求进行JWT校验,决定是否放行或拒绝
  • AuthController:对外暴露认证相关HTTP接口,接收登录凭证并返回令牌
  • AuthService:实现认证核心流程,包括用户校验、权限装配、令牌签发与刷新
  • AuthProperties:集中管理JWT密钥、过期时间、白名单路径等安全参数
  • JwtUtils:提供令牌的生成、解析、签名校验与载荷提取
  • AuthenticationException:统一抛出认证失败异常,便于全局异常处理

章节来源

架构总览

下图展示了从浏览器发起请求到服务端完成鉴权的整体流程,以及关键组件间的交互关系。

sequenceDiagram
participant C as "客户端"
participant F as "JwtAuthFilter"
participant A as "AuthController"
participant S as "AuthService"
participant U as "JwtUtils"
participant P as "AuthProperties"
C->>F : "携带Authorization头发起请求"
F->>F : "匹配白名单/忽略路径"
alt "需要鉴权"
F->>U : "解析并校验JWT"
U-->>F : "有效载荷/错误"
alt "令牌无效或过期"
F-->>C : "401/403响应"
else "令牌有效"
F->>S : "加载用户上下文/权限"
S-->>F : "上下文对象"
F->>A : "放行至控制器"
A-->>C : "业务响应"
end
else "白名单路径"
F->>A : "直接放行"
A-->>C : "业务响应"
end

图表来源

详细组件分析

JwtAuthFilter 过滤器

职责与行为

  • 拦截所有入站请求,判断是否命中白名单或静态资源
  • 从请求头中提取JWT令牌并进行解析与签名校验
  • 将解析出的用户信息与权限注入到当前请求上下文,供后续处理器使用
  • 对未认证或权限不足请求返回标准错误码

关键点

  • 白名单策略:允许匿名访问的路径(如登录、健康检查)
  • 令牌位置:通常从Authorization头获取Bearer Token
  • 错误处理:捕获解析异常并转换为统一的认证失败响应
flowchart TD
Start(["进入过滤器"]) --> CheckPath["判断是否白名单/静态资源"]
CheckPath --> |是| Pass["放行至控制器"]
CheckPath --> |否| ExtractToken["提取Authorization头中的令牌"]
ExtractToken --> Validate["调用JwtUtils校验令牌"]
Validate --> Valid{"校验通过?"}
Valid --> |否| Deny["返回401/403"]
Valid --> |是| BuildCtx["构建用户上下文/权限"]
BuildCtx --> Next["继续过滤器链/到达控制器"]

图表来源

章节来源

AuthController 控制器

职责与行为

  • 提供登录接口:接收用户名/密码,委托AuthService完成认证并签发JWT
  • 提供刷新接口:支持基于旧令牌换取新令牌(可结合黑名单/滑动窗口)
  • 提供登出接口:使旧令牌失效(可选,取决于是否启用令牌黑名单)

典型交互

  • 登录成功返回包含access_token与refresh_token的响应体
  • 刷新时校验refresh_token有效性并颁发新的access_token
  • 登出时将当前token加入黑名单或标记为已注销
sequenceDiagram
participant C as "客户端"
participant AC as "AuthController"
participant AS as "AuthService"
participant JU as "JwtUtils"
participant AP as "AuthProperties"
C->>AC : "POST /login {username,password}"
AC->>AS : "authenticate(username,password)"
AS->>JU : "generateAccessToken(user, properties)"
JU-->>AS : "access_token"
AS-->>AC : "{access_token, refresh_token}"
AC-->>C : "200 OK"
C->>AC : "POST /refresh {refresh_token}"
AC->>AS : "refresh(refresh_token)"
AS->>JU : "validateAndGenerateNew(token, properties)"
JU-->>AS : "new_access_token"
AS-->>AC : "{access_token}"
AC-->>C : "200 OK"

图表来源

章节来源

AuthService 服务

职责与行为

  • 认证主流程:校验用户身份、加载角色与权限、签发令牌
  • 刷新流程:校验refresh_token、生成新的access_token
  • 会话管理:维护活跃会话列表、支持强制下线与并发控制
  • 权限装配:将用户权限集合注入到上下文,供授权决策使用

注意

  • 与数据库或缓存交互以获取用户与权限信息
  • 与JwtUtils协作完成令牌生命周期管理
  • 与AuthProperties配合读取密钥、过期时间等参数

章节来源

AuthProperties 配置类

作用

  • 集中管理JWT相关安全参数,如:
    • 签名密钥(secret/key)
    • access_token与refresh_token过期时间
    • 白名单路径列表
    • 是否启用黑名单/撤销机制
    • 最大会话数、并发限制等

使用方式

  • 通过配置文件(如application.yaml)注入属性
  • 在过滤器与服务中读取配置,驱动鉴权与令牌策略

章节来源

JwtUtils 工具类

核心功能

  • 生成access_token与refresh_token
  • 解析并校验JWT签名与有效期
  • 从载荷中提取用户标识、角色与权限
  • 支持刷新令牌的重放防护(如一次性使用或短期有效)

测试覆盖

  • JwtUtilsTests验证了令牌的生成、解析与基本校验逻辑

章节来源

依赖分析

组件间耦合关系如下:

  • JwtAuthFilter依赖JwtUtils进行令牌校验,依赖AuthProperties决定白名单策略
  • AuthController依赖AuthService完成认证业务
  • AuthService依赖JwtUtils进行令牌签发与校验,依赖AuthProperties读取安全参数
  • 所有组件通过统一的AuthenticationException对外暴露认证失败语义
graph LR
Filter["JwtAuthFilter"] --> Utils["JwtUtils"]
Filter --> Props["AuthProperties"]
Controller["AuthController"] --> Service["AuthService"]
Service --> Utils
Service --> Props
Service --> DB["用户/权限存储"]

图表来源

章节来源

性能考虑

  • 令牌校验开销:尽量将高频校验逻辑(如签名验证)优化为本地计算;必要时引入缓存减少重复查询
  • 会话管理:活跃会话表/缓存需设计合理的索引与淘汰策略,避免内存膨胀
  • 刷新令牌:建议设置较短的access_token过期时间与较长的refresh_token周期,降低频繁刷新带来的压力
  • 白名单与静态资源:尽早放行以减少过滤器链开销
  • 并发控制:限制单用户并发会话数,防止资源滥用

故障排查指南

常见问题与定位

  • 401 未认证:检查Authorization头是否正确携带Bearer Token;确认白名单配置是否误拦截
  • 403 权限不足:检查用户角色与权限是否已正确加载;确认接口是否需要特定权限
  • 令牌过期:调整access_token过期时间或实现自动刷新;检查客户端是否在过期前刷新
  • 刷新失败:检查refresh_token是否已被使用或撤销;确认黑名单机制是否生效
  • 签名错误:核对AuthProperties中的密钥是否与签发端一致

定位步骤

  • 查看过滤器日志:确认是否进入鉴权分支、令牌解析结果
  • 检查服务层日志:确认用户与权限加载是否成功
  • 复现最小用例:构造仅含必要字段的请求,逐步缩小问题范围

章节来源

结论

本系统采用JWT无状态认证,结合过滤器前置鉴权与统一异常处理,实现了清晰的鉴权边界与可扩展的权限模型。通过AuthProperties集中管理安全参数,JwtUtils提供稳定的令牌处理能力,AuthService串联认证与会话管理。建议在部署时严格管理密钥、合理设置过期时间、启用刷新与黑名单机制,并结合监控与审计提升安全性与可观测性。

附录

  • 安全配置最佳实践
    • 使用强随机密钥并定期轮换
    • 区分access_token与refresh_token的过期策略
    • 启用HTTPS传输,防止中间人攻击
    • 记录登录与操作日志,便于审计与溯源
  • 常见安全问题防护
    • 防重放攻击:对敏感接口增加nonce/time-window校验或使用一次性refresh_token
    • 会话劫持:绑定设备指纹或IP段(谨慎使用),加强Cookie/Token存储安全
    • 暴力破解:对登录接口实施限流与验证码
    • 越权访问:在服务层进行细粒度权限校验,不仅依赖前端控制