Files
workspace/code/fms/.qoder/repowiki/zh/content/API接口文档/认证接口.md
T
2026-08-23 21:02:41 +08:00

17 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) - [JwtAuthFilter.java](file://fms-api/src/main/java/cn/g3soft/fmsapi/config/JwtAuthFilter.java) - [JwtUtils.java](file://fms-api/src/main/java/cn/g3soft/fmsapi/utils/JwtUtils.java) - [AuthProperties.java](file://fms-api/src/main/java/cn/g3soft/fmsapi/config/AuthProperties.java) - [ApiResponse.java](file://fms-api/src/main/java/cn/g3soft/fmsapi/utils/ApiResponse.java) - [AuthenticationException.java](file://fms-api/src/main/java/cn/g3soft/fmsapi/exception/AuthenticationException.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)

目录

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

简介

本文件为 FMS 系统认证相关 RESTful API 的权威文档,覆盖用户登录、令牌校验与会话管理等能力。文档包含:

  • 所有认证端点的 HTTP 方法、URL、请求参数、响应格式与错误码
  • JWT 认证流程的完整调用示例(登录、获取令牌、权限验证)
  • 认证过滤器的工作原理与拦截机制
  • 常见认证错误处理与故障排除建议

项目结构

认证功能主要位于后端 fms-api 模块中,关键目录与职责如下:

  • controller:对外暴露认证接口
  • service:认证业务逻辑、会话管理、登录日志记录
  • config:认证过滤器、配置属性
  • utils:JWT 工具、统一响应体
  • exception:认证异常类型
graph TB
Client["客户端"] --> Filter["JwtAuthFilter<br/>请求拦截与鉴权"]
Filter --> Controller["AuthController<br/>/auth/login"]
Controller --> Service["AuthService<br/>登录校验、生成Token、记录日志"]
Service --> Db["DbUtils<br/>查询用户信息"]
Service --> Jwt["JwtUtils<br/>签发/解析JWT"]
Service --> Session["ActiveSessionRegistry<br/>活跃会话管理"]
Service --> Log["LoginLogService<br/>登录日志记录"]
Filter --> Session
Filter --> Jwt

图表来源

章节来源

核心组件

  • 认证控制器:提供登录接口,接收 orgid、userid、password,返回统一响应体
  • 认证服务:执行用户校验、密码比对、生成 JWT、激活会话、记录登录日志
  • JWT 工具:负责密钥初始化、签发与解析令牌
  • 认证过滤器:对所有非登录请求进行 Token 校验与活跃会话检查,设置上下文
  • 会话注册表:维护当前活跃会话,支持单点互踢等策略
  • 登录日志:记录登录成功/失败及原因
  • 统一响应体:定义标准 code/message/data 结构与常用错误码

章节来源

架构总览

下图展示了从客户端发起登录到后续受保护接口调用的完整流程,包括过滤器拦截、JWT 校验与会话检查。

sequenceDiagram
participant C as "客户端"
participant F as "JwtAuthFilter"
participant A as "AuthController"
participant S as "AuthService"
participant J as "JwtUtils"
participant R as "ActiveSessionRegistry"
participant L as "LoginLogService"
C->>A : POST /auth/login {orgid, userid, password}
A->>S : login(orgid, userid, password, request)
S->>S : 校验用户/密码
alt 认证成功
S->>J : generateToken(userId, orgId, sessionId)
S->>R : activate(orgId, userId, sessionId)
S->>L : recordLogin(成功, sessionId)
S-->>A : {token, orgid, user}
A-->>C : ApiResponse.success(...)
else 认证失败
S->>L : recordLogin(失败, 原因)
S-->>A : Optional.empty()
A-->>C : ApiResponse.fail(401, 错误信息)
end
Note over C,F : 后续受保护接口调用
C->>F : 携带 Authorization : Bearer <token>
F->>J : parseToken(token)
F->>R : hasActiveSession(orgId, userId)
F->>R : isActive(orgId, userId, sessionId)
alt 通过
F->>F : 设置 OrgContext
F-->>C : 放行至业务接口
else 未通过
F-->>C : ApiResponse.fail(401/40101, 错误信息)
end

图表来源

详细组件分析

认证控制器 AuthController

  • 路径与方法:POST /auth/login
  • 请求体:JSON 对象,包含 orgid、userid、password
  • 参数校验:orgid、userid 为空时抛出业务异常
  • 成功响应:code=0,data 包含 token、orgid、user(含 id、account、name)
  • 失败响应:code=401,message 提示“机构码、账号或密码错误”
flowchart TD
Start(["进入 /auth/login"]) --> Parse["解析请求体<br/>orgid, userid, password"]
Parse --> Validate{"orgid/userid 是否为空?"}
Validate --> |是| ThrowErr["抛出业务异常"]
Validate --> |否| CallSvc["调用 AuthService.login(...)"]
CallSvc --> Result{"是否返回用户信息?"}
Result --> |否| FailResp["返回 401 错误"]
Result --> |是| SuccessResp["返回 200 + token/orgid/user"]
ThrowErr --> End(["结束"])
FailResp --> End
SuccessResp --> End

图表来源

章节来源

认证服务 AuthService

  • 登录流程:
    • 规范化 orgid(大写)、userid(去空白)
    • 查询用户并校验密码(安全比较)
    • 生成 JWT(包含 userId、orgId、sessionId)
    • 激活会话(ActiveSessionRegistry)
    • 记录登录日志(成功/失败)
    • 组装返回数据(token、orgid、user)
  • 密码比较:使用常量时间比较避免时序攻击
  • 错误处理:账号不存在或密码错误均记录日志并返回空结果
flowchart TD
S0["开始 login"] --> N1["规范化 orgid/userid"]
N1 --> Q1["查询用户"]
Q1 --> E1{"找到用户?"}
E1 --> |否| L1["记录登录失败(账号不存在)"] --> R1["返回空"]
E1 --> |是| P1["校验密码"]
P1 --> E2{"密码正确?"}
E2 --> |否| L2["记录登录失败(密码错误)"] --> R2["返回空"]
E2 --> |是| T1["生成JWT(含sessionId)"]
T1 --> A1["激活会话"]
A1 --> L3["记录登录成功(含sessionId)"]
L3 --> D1["组装返回{token, orgid, user}"]
D1 --> R3["返回结果"]

图表来源

章节来源

JWT 工具 JwtUtils

  • 初始化:读取配置 fms.auth.jwt-secret、jwt-expiration,校验长度与有效期
  • 签发:生成包含 subject(userId)、id(sessionId)、claim(orgId)、issuedAt、expiration 的 JWT
  • 解析:提取 userId、orgId、sessionId,缺失则抛异常
  • 组织上下文:配合过滤器设置 OrgContext
classDiagram
class JwtUtils {
+generateToken(userId, orgId, sessionId) String
+parseToken(token) TokenClaims
+getOrgId(token) String
}
class TokenClaims {
+String userId
+String orgId
+String sessionId
}
JwtUtils --> TokenClaims : "返回"

图表来源

章节来源

认证过滤器 JwtAuthFilter

  • 过滤范围:跳过 OPTIONS 预检与 /auth/login
  • 鉴权步骤:
    • 从 Authorization 头提取 Bearer Token
    • 解析 Token 获取 claims
    • 校验是否存在活跃会话
    • 校验当前 sessionId 是否仍有效(防止多设备互踢)
    • 将 orgId、userId 写入上下文,放行后清理
  • 失败响应:统一返回 200 状态码 + ApiResponse.fail(code, message)
flowchart TD
F0["进入 doFilterInternal"] --> H0{"是否OPTIONS或/login?"}
H0 --> |是| Skip["跳过过滤"] --> Next["继续链式过滤"]
H0 --> |否| G0["提取Authorization头"]
G0 --> P0["解析Token"]
P0 --> S0{"存在活跃会话?"}
S0 --> |否| U0["返回401 未登录或失效"]
S0 --> |是| I0{"sessionId仍有效?"}
I0 --> |否| K0["返回40101 被其他设备顶替"]
I0 --> |是| C0["设置OrgContext"] --> Next
Next --> Clean["finally清理上下文"]

图表来源

章节来源

会话管理与登录日志

  • ActiveSessionRegistry:维护每个用户的活跃会话集合,支持激活、检查、有效性判断
  • LoginLogService:记录登录成功/失败、原因、会话ID、请求信息等,便于审计与排查

章节来源

依赖关系分析

  • 控制器依赖服务层,服务层依赖数据库工具、JWT 工具、会话注册表与日志服务
  • 过滤器依赖 JWT 工具与会话注册表,用于鉴权与上下文设置
  • 配置类集中管理 JWT 密钥与过期时间
graph LR
AC["AuthController"] --> AS["AuthService"]
AS --> DBU["DbUtils"]
AS --> JU["JwtUtils"]
AS --> ASR["ActiveSessionRegistry"]
AS --> LLS["LoginLogService"]
JAF["JwtAuthFilter"] --> JU
JAF --> ASR
JU --> AP["AuthProperties"]

图表来源

章节来源

性能考虑

  • 密码比较采用常量时间比较,降低时序攻击风险
  • JWT 签发与解析基于高效库实现,注意合理设置过期时间以平衡安全性与性能
  • 活跃会话检查为内存级操作,适合高并发场景;如需持久化可结合缓存
  • 登录日志建议异步落库,避免阻塞主流程

故障排除指南

  • 登录失败
    • 检查 orgid、userid、password 是否正确
    • 查看登录日志中的失败原因(账号不存在、密码错误)
  • 鉴权失败(401)
    • 确认 Authorization 头格式为 Bearer
    • 检查 Token 是否过期或被撤销
  • 会话被顶替(40101)
    • 同一账号在其他设备登录后,旧设备会话失效,需重新登录
  • 配置问题
    • fms.auth.jwt-secret 长度不足 32 字节会导致启动失败
    • fms.auth.jwt-expiration 必须大于 0

章节来源

结论

FMS 认证体系通过控制器、服务层、JWT 工具与过滤器协同工作,实现了安全的登录、令牌签发与会话管理。统一响应体与明确的错误码便于前端集成与排错。建议在生产环境严格配置 JWT 密钥与过期时间,并结合登录日志进行审计与监控。

附录:API 规范与调用示例

统一响应体

  • 结构:{ code, message, data }
  • 常用码值:
    • 0:成功
    • 401:未登录或凭证无效
    • 40101:会话被其他设备顶替
    • 1000:业务异常
    • 2001:保存错误
    • 500:系统错误

章节来源

登录接口

  • 方法:POST
  • 路径:/auth/login
  • 请求体:
    • orgid:字符串,必填
    • userid:字符串,必填
    • password:字符串,必填
  • 成功响应:
    • code=0
    • data.token:JWT 字符串
    • data.orgid:机构码
    • data.user:{ id, account, name }
  • 失败响应:
    • code=401
    • message:错误描述

章节来源

令牌校验与会话管理

  • 校验方式:在后续受保护接口的请求头中添加 Authorization: Bearer
  • 过滤器行为:
    • 解析 Token,校验签名与有效期
    • 检查活跃会话是否存在且 sessionId 匹配
    • 设置 OrgContext 后放行
  • 失败响应:
    • 401:未登录或凭证无效
    • 40101:账号已在其他设备登录,请重新登录

章节来源

完整调用示例(文字版)

  • 登录
    • 发送 POST /auth/login,请求体包含 orgid、userid、password
    • 成功后获取 data.token
  • 访问受保护接口
    • 在请求头添加 Authorization: Bearer
    • 若返回 40101,说明会话被顶替,需重新登录
  • 退出/注销
    • 可通过服务端提供的注销接口或使 Token 失效(如加入黑名单)实现;当前代码未提供显式注销端点,可按需扩展

章节来源