# 认证模块(auth) > 证据来源:[SRC-FEAT-01] [SRC-API-01] [SRC-CODE-01:module/auth/] --- ## 1. 模块定位 - **模块目标**:负责用户身份验证(企业微信OAuth + 账号密码备选)和 JWT Token 的签发、校验,为所有其他模块提供鉴权基础。 - **解决问题**:500人规模的企业内部系统,需要统一身份验证入口,并将身份与角色绑定,为下游数据隔离提供 `userId + role + departmentId` 上下文。 --- ## 2. 功能清单 [SRC-API-01:四、API 接口设计 / SRC-CODE-01:module/auth/] | 功能名称 | 功能描述 | 输入 | 输出 | 依赖模块 | |---------|---------|------|------|---------| | 企业微信 OAuth 登录 | 通过企业微信授权 code 换取用户身份,查找系统用户,签发 JWT | wx_code | JWT Token + 用户信息(LoginResponse) | system(查sys_user) | | 账号密码登录(备选) | 用用户名+密码登录,BCrypt 验证密码 | username, password | JWT Token + 用户信息 | system(查sys_user) | | 获取当前用户信息 | 解析 Token 返回用户基本信息 | Authorization Header | UserInfoResponse | - | | 微信小程序登录(预留) | 通过小程序 code 获取用户信息 | WechatLoginRequest | JWT Token | system | | Token 携带与拦截 | AuthInterceptor 拦截所有受保护请求,提取 Token 注入 UserContext | Authorization: Bearer {token} | UserContext(ThreadLocal) | - | --- ## 3. 核心逻辑 ### 3.1 业务规则 - 企业微信登录路径:前端传 code → 后端调 weixin-java-cp SDK 换 `access_token` → 获取 `wx_userid` → 查 `sys_user.wx_userid` 匹配 → 用户不存在则返回错误(不自动注册)[SRC-FEAT-01] - JWT Payload 包含:userId、role、departmentId,有效期由配置决定 - 密码存储:BCrypt 加密(Spring Security 6.x),初始管理员密码 `admin123` 已预置 [SRC-SQL-01:5.4] ### 3.2 校验逻辑 | 校验项 | 规则 | 失败响应 | |-------|------|---------| | wx_userid 是否存在于 sys_user | 必须已由管理员录入 | 返回错误:用户未录入,请联系管理员 | | sys_user.status | 必须为 0(启用) | 返回错误:账号已禁用 | | Token 有效性 | 未过期、签名正确 | 返回 401 | | 受保护接口 Token 缺失 | 无 Authorization Header | 返回 401 | ### 3.3 状态流转 ```mermaid stateDiagram-v2 [*] --> 未认证 未认证 --> 已认证 : 登录成功(JWT签发) 已认证 --> 未认证 : Token过期 / 主动登出 已认证 --> 已认证 : Token续期(如有配置) ``` --- ## 4. 数据结构 ### 4.1 涉及数据表 **sys_user**(读取,不由本模块创建)[SRC-SQL-01] | 字段 | 类型 | 说明 | |------|------|------| | id | BIGINT | 用户主键 | | wx_userid | VARCHAR(100) | 企业微信用户ID(唯一索引 uk_wx_userid) | | username | VARCHAR(50) | 账号密码登录用账号(唯一索引 uk_username) | | password | VARCHAR(100) | BCrypt加密密码 | | role | TINYINT | 0-管理员 / 1-讲师 / 2-学员 | | department_id | BIGINT | 所属部门ID(会注入 JWT Payload) | | status | TINYINT | 0-启用 / 1-禁用 | ### 4.2 DTO/VO 定义 [SRC-CODE-01:module/auth/dto/] | 类名 | 方向 | 关键字段 | |------|------|---------| | LoginRequest | 入参 | username, password | | WechatLoginRequest | 入参 | code(企业微信授权码) | | LoginResponse | 出参 | token, userId, realName, role, departmentId | | UserInfoResponse | 出参 | 同 LoginResponse(从 Token 解析) | --- ## 5. 对外接口 [SRC-API-01] | API 名称 | 方法 | 路径 | 权限 | |---------|------|------|------| | 企业微信登录 | POST | /api/auth/wechat/login | 公开 | | 账号密码登录 | POST | /api/auth/login | 公开 | | 获取当前用户 | GET | /api/auth/me | 需 Token | **事件机制**:登录成功后,UserContext(ThreadLocal)持有用户信息,供同请求链路的所有 Service 使用,请求结束后清除。[SRC-CODE-01:common/context/UserContextHolder.java] --- ## 6. 异常与边界处理 | 场景 | 处理方式 | |------|---------| | 企业微信 API 调用超时/失败 | 返回 503,提示"企业微信服务暂时不可用,请稍后重试" | | 企业微信 code 已使用(重放) | 企业微信 SDK 返回错误,转化为 400 | | 用户 wx_userid 存在但账号被禁用(status=1) | 返回 403,提示"账号已禁用,请联系管理员" | | sys_user 中无对应 wx_userid | 返回 403,提示"用户未录入系统,请联系管理员" | | Token 格式错误(非JWT) | AuthInterceptor 捕获,返回 401 | | Token 过期 | AuthInterceptor 捕获,返回 401,前端跳转登录页 | | 并发登录(同一账号多端) | 当前设计无限制,多端独立 Token 有效 |