# 用户认证系统 **本文档引用的文件** - [server/src/modules/auth/auth.controller.ts](file://server/src/modules/auth/auth.controller.ts) - [server/src/modules/auth/auth.service.ts](file://server/src/modules/auth/auth.service.ts) - [server/src/middleware/auth.ts](file://server/src/middleware/auth.ts) - [server/src/middleware/auth.js](file://server/src/middleware/auth.js) - [server/src/middleware/security.ts](file://server/src/middleware/security.ts) - [server/src/middleware/rate-limiter.ts](file://server/src/middleware/rate-limiter.ts) - [server/src/middleware/errorHandler.ts](file://server/src/middleware/errorHandler.ts) - [server/src/config/index.ts](file://server/src/config/index.ts) - [server/src/models/index.ts](file://server/src/models/index.ts) - [server/src/types/index.ts](file://server/src/types/index.ts) - [server/src/app.ts](file://server/src/app.ts) - [server/src/services/redis.service.js](file://server/src/services/redis.service.js) ## 目录 1. [简介](#简介) 2. [项目结构](#项目结构) 3. [核心组件](#核心组件) 4. [架构总览](#架构总览) 5. [详细组件分析](#详细组件分析) 6. [依赖关系分析](#依赖关系分析) 7. [性能考虑](#性能考虑) 8. [故障排除指南](#故障排除指南) 9. [结论](#结论) 10. [附录](#附录) ## 简介 本技术文档面向用户认证系统,重点覆盖手机号登录流程、JWT令牌生成与验证机制、权限控制策略、认证中间件实现原理、Token刷新机制与用户会话管理、移动端登录适配、多设备登录管理、登录状态持久化等主题。文档同时提供在控制器中使用认证中间件、权限检查、异常处理的具体示例路径,并结合仓库现有代码进行深入分析。 ## 项目结构 认证系统主要由以下层次构成: - 应用入口与路由:Koa 应用初始化、全局中间件注册、路由挂载 - 认证控制器:对外暴露手机号登录、验证码发送、用户信息获取与更新等接口 - 认证服务:负责验证码生成与校验、JWT签发、用户查找/创建、用户信息查询 - 认证中间件:统一处理 Authorization 头解析、JWT校验、开发环境开关 - 安全中间件:XSS/SQL注入防护、敏感数据脱敏 - 限流中间件:API全局限流、登录接口限流、验证码发送限流、TTS/上传限流 - 错误处理中间件:统一捕获并格式化错误响应 - 配置中心:JWT密钥、过期时间、模型配置等 - 数据模型:Prisma 客户端连接与数据库交互 - 类型定义:用户、JWT载荷、响应体等类型声明 ```mermaid graph TB App["应用入口
server/src/app.ts"] --> Cfg["配置中心
server/src/config/index.ts"] App --> Sec["安全中间件
server/src/middleware/security.ts"] App --> Lim["限流中间件
server/src/middleware/rate-limiter.ts"] App --> Err["错误处理中间件
server/src/middleware/errorHandler.ts"] App --> AuthCtrl["认证控制器
server/src/modules/auth/auth.controller.ts"] AuthCtrl --> AuthSvc["认证服务
server/src/modules/auth/auth.service.ts"] AuthCtrl --> AuthMW["认证中间件
server/src/middleware/auth.ts"] AuthSvc --> Types["类型定义
server/src/types/index.ts"] AuthSvc --> Models["数据模型
server/src/models/index.ts"] AuthMW --> Cfg AuthMW --> Err Sec --> App Lim --> App Err --> App ``` **图表来源** - [server/src/app.ts:57-130](file://server/src/app.ts#L57-L130) - [server/src/modules/auth/auth.controller.ts:1-94](file://server/src/modules/auth/auth.controller.ts#L1-L94) - [server/src/modules/auth/auth.service.ts:1-115](file://server/src/modules/auth/auth.service.ts#L1-L115) - [server/src/middleware/auth.ts:1-81](file://server/src/middleware/auth.ts#L1-L81) - [server/src/middleware/security.ts:1-154](file://server/src/middleware/security.ts#L1-L154) - [server/src/middleware/rate-limiter.ts:1-120](file://server/src/middleware/rate-limiter.ts#L1-L120) - [server/src/middleware/errorHandler.ts:1-67](file://server/src/middleware/errorHandler.ts#L1-L67) - [server/src/config/index.ts:69-81](file://server/src/config/index.ts#L69-L81) - [server/src/models/index.ts:1-15](file://server/src/models/index.ts#L1-L15) - [server/src/types/index.ts:66-82](file://server/src/types/index.ts#L66-L82) **章节来源** - [server/src/app.ts:57-130](file://server/src/app.ts#L57-L130) ## 核心组件 - 认证控制器:提供 /api/auth/send-code、/api/auth/login、/api/auth/user-info 等接口;使用认证中间件保护用户信息读取与更新 - 认证服务:生成/校验短信验证码、签发JWT、用户注册与登录、用户信息查询 - 认证中间件:解析Authorization头、校验JWT、区分开发/生产环境行为 - 安全中间件:XSS过滤、SQL注入检测、响应敏感数据脱敏 - 限流中间件:基于Redis/Memory的速率限制器,针对不同场景配置限流策略 - 错误处理中间件:统一捕获异常,按环境输出详细或简要错误信息 - 配置中心:集中管理JWT密钥、过期时间、模型配置等 - 数据模型:Prisma客户端连接数据库,提供用户查询与更新能力 - 类型定义:JwtPayload、IUser、ApiResponse等类型约束 **章节来源** - [server/src/modules/auth/auth.controller.ts:1-94](file://server/src/modules/auth/auth.controller.ts#L1-L94) - [server/src/modules/auth/auth.service.ts:1-115](file://server/src/modules/auth/auth.service.ts#L1-L115) - [server/src/middleware/auth.ts:1-81](file://server/src/middleware/auth.ts#L1-L81) - [server/src/middleware/security.ts:1-154](file://server/src/middleware/security.ts#L1-L154) - [server/src/middleware/rate-limiter.ts:1-120](file://server/src/middleware/rate-limiter.ts#L1-L120) - [server/src/middleware/errorHandler.ts:1-67](file://server/src/middleware/errorHandler.ts#L1-L67) - [server/src/config/index.ts:69-81](file://server/src/config/index.ts#L69-L81) - [server/src/models/index.ts:1-15](file://server/src/models/index.ts#L1-L15) - [server/src/types/index.ts:66-82](file://server/src/types/index.ts#L66-L82) ## 架构总览 认证系统采用分层架构,控制器负责HTTP接口,服务层封装业务逻辑,中间件负责横切关注点(安全、限流、认证),配置与模型提供基础设施支撑。 ```mermaid sequenceDiagram participant Client as "客户端" participant Router as "认证控制器" participant Service as "认证服务" participant JWT as "JWT库" participant DB as "Prisma/数据库" Client->>Router : "POST /api/auth/send-code" Router->>Service : "generateSmsCode(phone)" Service->>Service : "生成4位验证码并缓存(5分钟)" Service-->>Router : "返回验证码(开发环境)" Router-->>Client : "响应 : {code,message,data}" Client->>Router : "POST /api/auth/login" Router->>Service : "loginWithPhone(phone, code)" Service->>Service : "校验验证码(开发环境可跳过)" Service->>DB : "查找/创建用户" DB-->>Service : "用户记录" Service->>JWT : "sign(payload, secret, {expiresIn})" JWT-->>Service : "返回token" Service-->>Router : "{token,user}" Router-->>Client : "响应 : {code,message,data}" ``` **图表来源** - [server/src/modules/auth/auth.controller.ts:11-52](file://server/src/modules/auth/auth.controller.ts#L11-L52) - [server/src/modules/auth/auth.service.ts:11-97](file://server/src/modules/auth/auth.service.ts#L11-L97) ## 详细组件分析 ### 认证控制器分析 - 接口职责 - 发送验证码:校验手机号格式,生成并返回验证码(开发环境总是返回) - 手机号登录:校验手机号格式,支持免验证码登录(开发环境或特定code) - 用户信息:通过认证中间件获取当前用户ID,查询用户信息 - 更新用户信息:通过认证中间件获取当前用户ID,更新昵称/头像 - 控制器与中间件协作:使用 authMiddleware 保护受保护接口,将用户信息写入 ctx.state.user ```mermaid flowchart TD Start(["请求进入控制器"]) --> Parse["解析请求体/查询参数"] Parse --> Validate{"参数校验通过?"} Validate --> |否| ThrowErr["抛出BadRequestError"] Validate --> |是| Route{"具体路由?"} Route --> SendCode["发送验证码"] Route --> Login["手机号登录"] Route --> UserInfo["获取用户信息"] Route --> UpdateInfo["更新用户信息"] SendCode --> DevCheck{"开发环境?"} DevCheck --> |是| ReturnCode["返回验证码"] DevCheck --> |否| StoreCode["存储验证码(5分钟)"] StoreCode --> ReturnCode Login --> SkipVerify{"跳过验证码校验?"} SkipVerify --> |是| FindOrCreate["查找/创建用户"] SkipVerify --> |否| VerifyCode["校验验证码"] VerifyCode --> FindOrCreate FindOrCreate --> SignToken["签发JWT"] SignToken --> ReturnLogin["返回token与用户信息"] UserInfo --> LoadUser["从ctx.state.user读取userId"] LoadUser --> QueryUser["查询用户信息"] QueryUser --> ReturnUser["返回用户信息"] UpdateInfo --> LoadUser2["从ctx.state.user读取userId"] LoadUser2 --> UpdateUser["更新昵称/头像"] UpdateUser --> ReturnUpdate["返回更新结果"] ``` **图表来源** - [server/src/modules/auth/auth.controller.ts:11-92](file://server/src/modules/auth/auth.controller.ts#L11-L92) **章节来源** - [server/src/modules/auth/auth.controller.ts:1-94](file://server/src/modules/auth/auth.controller.ts#L1-L94) ### 认证服务分析 - 验证码机制 - 生成:4位数字验证码,存储于Map,5分钟过期 - 校验:检查是否存在、是否过期、是否匹配,匹配后删除 - JWT签发 - 载荷包含 userId、phone - 使用固定密钥与7天过期时间 - 登录/注册流程 - 免验证码登录:开发环境或code为特定值时跳过校验 - 查找用户,不存在则创建默认用户 - 生成token并返回用户信息 ```mermaid classDiagram class AuthService { +generateSmsCode(phone) string +verifySmsCode(phone, code) boolean +generateToken(userId, phone) string +loginWithPhone(phone, code) Promise~LoginResult~ +getUserInfo(userId) Promise~UserInfo~ } class JwtService { +sign(payload, secret, options) string +verify(token, secret) Payload } class PrismaClient { +userfindFirst(where) User +usercreate(data) User +userupdate(where, data) User } AuthService --> JwtService : "使用" AuthService --> PrismaClient : "查询/创建/更新" ``` **图表来源** - [server/src/modules/auth/auth.service.ts:11-97](file://server/src/modules/auth/auth.service.ts#L11-L97) - [server/src/config/index.ts:77-81](file://server/src/config/index.ts#L77-L81) - [server/src/models/index.ts:1-15](file://server/src/models/index.ts#L1-L15) **章节来源** - [server/src/modules/auth/auth.service.ts:1-115](file://server/src/modules/auth/auth.service.ts#L1-L115) ### 认证中间件分析 - 开发环境开关:通过环境变量控制是否启用认证 - Authorization头解析:Bearer Token格式校验 - JWT验证:使用固定密钥验证token有效性,区分过期与无效错误 - 可选认证:optionalAuth在无token或token无效时,降级为测试用户 ```mermaid sequenceDiagram participant Client as "客户端" participant MW as "认证中间件" participant JWT as "JWT库" participant Next as "后续中间件/控制器" Client->>MW : "携带Authorization头的请求" MW->>MW : "检查AUTH_ENABLED" alt 未启用 MW->>MW : "设置测试用户到ctx.state.user" MW->>Next : "继续执行" else 启用 MW->>MW : "解析Authorization头" MW->>JWT : "verify(token, secret)" alt 成功 JWT-->>MW : "payload" MW->>Next : "继续执行" else 失败 JWT-->>MW : "抛出错误" MW->>Client : "返回401错误" end end ``` **图表来源** - [server/src/middleware/auth.ts:7-49](file://server/src/middleware/auth.ts#L7-L49) - [server/src/middleware/auth.js:44-94](file://server/src/middleware/auth.js#L44-L94) **章节来源** - [server/src/middleware/auth.ts:1-81](file://server/src/middleware/auth.ts#L1-L81) - [server/src/middleware/auth.js:1-137](file://server/src/middleware/auth.js#L1-L137) ### 安全中间件分析 - XSS防护:递归清理请求体与查询参数中的危险字符,设置安全响应头 - SQL注入防护:检测请求参数中的常见注入模式,拦截非法请求 - 敏感数据脱敏:对响应体中的敏感字段进行脱敏处理 **章节来源** - [server/src/middleware/security.ts:1-154](file://server/src/middleware/security.ts#L1-L154) ### 限流中间件分析 - 限流器选择:优先使用Redis,不可用时回退到内存限流器 - 场景化限流: - API全局限流:每分钟100次 - 登录接口限流:每分钟5次,封禁5分钟 - 验证码发送限流:每分钟1次,每小时5次 - TTS/上传限流:按用户维度限流 - 错误响应:429状态码,包含retry-after提示 **章节来源** - [server/src/middleware/rate-limiter.ts:1-120](file://server/src/middleware/rate-limiter.ts#L1-L120) - [server/src/services/redis.service.js:232-325](file://server/src/services/redis.service.js#L232-L325) ### 错误处理与类型系统 - 统一错误处理:捕获异常,按环境输出详细或简要信息 - 自定义错误类型:AppError、UnauthorizedError、ForbiddenError、NotFoundError、BadRequestError、QuotaExceededError - 类型系统:JwtPayload、IUser、ApiResponse等类型约束 **章节来源** - [server/src/middleware/errorHandler.ts:1-67](file://server/src/middleware/errorHandler.ts#L1-L67) - [server/src/types/index.ts:66-82](file://server/src/types/index.ts#L66-L82) ### 配置与数据模型 - 配置中心:JWT密钥与过期时间、模型配置等 - 数据模型:Prisma客户端连接数据库,提供用户CRUD能力 **章节来源** - [server/src/config/index.ts:69-81](file://server/src/config/index.ts#L69-L81) - [server/src/models/index.ts:1-15](file://server/src/models/index.ts#L1-L15) ## 依赖关系分析 认证系统各组件之间的依赖关系如下: ```mermaid graph LR AuthCtrl["auth.controller.ts"] --> AuthSvc["auth.service.ts"] AuthCtrl --> AuthMW["auth.ts"] AuthCtrl --> Models["models/index.ts"] AuthSvc --> Config["config/index.ts"] AuthSvc --> Types["types/index.ts"] AuthMW --> Config AuthMW --> ErrorHandler["errorHandler.ts"] Security["security.ts"] --> App["app.ts"] RateLimiter["rate-limiter.ts"] --> App ErrorHandler --> App App --> Router["app.ts 路由注册"] ``` **图表来源** - [server/src/modules/auth/auth.controller.ts:1-94](file://server/src/modules/auth/auth.controller.ts#L1-L94) - [server/src/modules/auth/auth.service.ts:1-115](file://server/src/modules/auth/auth.service.ts#L1-L115) - [server/src/middleware/auth.ts:1-81](file://server/src/middleware/auth.ts#L1-L81) - [server/src/middleware/errorHandler.ts:1-67](file://server/src/middleware/errorHandler.ts#L1-L67) - [server/src/middleware/security.ts:1-154](file://server/src/middleware/security.ts#L1-L154) - [server/src/middleware/rate-limiter.ts:1-120](file://server/src/middleware/rate-limiter.ts#L1-L120) - [server/src/app.ts:26-128](file://server/src/app.ts#L26-L128) **章节来源** - [server/src/app.ts:26-128](file://server/src/app.ts#L26-L128) ## 性能考虑 - 限流策略:针对高频接口(登录、验证码、TTS、上传)实施差异化限流,避免滥用与资源耗尽 - 缓存与存储:Redis可用时优先使用,不可用时回退内存限流器;存储类型可配置(OSS/本地) - 中间件顺序:安全与限流中间件置于错误处理之前,确保异常请求被尽早拦截 - JWT过期:7天有效期,建议在移动端实现Token刷新策略以提升用户体验 ## 故障排除指南 - 认证失败 - 缺少Authorization头:检查请求头格式是否为Bearer Token - Token无效或过期:确认密钥与过期时间配置一致,重新登录获取新Token - 开发环境认证开关:设置AUTH_ENABLED=true启用严格认证 - 验证码问题 - 验证码未过期但无法使用:检查验证码存储是否被提前删除 - 开发环境验证码:验证码会在响应中直接返回,便于调试 - 限流触发 - 429错误:查看Retry-After头部,等待冷却时间后重试 - 登录频繁:调整登录限流策略或使用免验证码登录(开发环境) - 错误响应 - 统一错误格式:code、message、data字段;开发环境附加stack信息 **章节来源** - [server/src/middleware/auth.ts:22-48](file://server/src/middleware/auth.ts#L22-L48) - [server/src/middleware/rate-limiter.ts:60-71](file://server/src/middleware/rate-limiter.ts#L60-L71) - [server/src/middleware/errorHandler.ts:3-24](file://server/src/middleware/errorHandler.ts#L3-L24) ## 结论 本认证系统以Koa为核心,结合JWT、中间件与限流策略,实现了手机号登录、验证码机制、用户信息管理与安全防护。控制器通过认证中间件保护接口,服务层封装业务逻辑,配置与模型提供基础设施支撑。系统具备良好的扩展性与安全性,适合在移动端与多设备场景下部署使用。 ## 附录 ### 移动端登录适配与多设备登录管理 - 移动端登录适配 - 使用Bearer Token作为认证凭据,遵循标准OAuth2实践 - 在应用启动时请求验证码,随后调用登录接口获取Token - 将Token持久化存储于安全容器(如Keychain/Keystore),避免明文存储 - 多设备登录管理 - 当前实现未提供设备维度的Token管理策略 - 建议在用户表增加device_id或token_revocation表,实现单点登录或多设备登录控制 - 结合Redis实现Token黑名单,支持强制下线或撤销特定设备Token ### 登录状态持久化 - Token持久化 - 建议在移动端实现Token刷新机制:当Token即将过期时自动刷新 - 刷新接口可设计为:携带refresh_token换取新的access_token - 会话状态 - 服务端采用无状态JWT,无需维护会话状态 - 若需强制退出或限制登录,可在服务端维护Token黑名单或用户状态表 ### 权限控制策略 - 基于角色的权限控制 - 当前系统通过memberLevel字段标识用户等级,可用于差异化权限控制 - 建议在中间件中增加权限检查函数,按等级开放不同接口 - 接口级权限 - 对高价值接口(如支付、敏感信息)增加更严格的校验与审计 ### 在控制器中使用认证中间件与权限检查示例路径 - 使用认证中间件保护接口 - 示例路径:[server/src/modules/auth/auth.controller.ts:55-64](file://server/src/modules/auth/auth.controller.ts#L55-L64) - 读取当前用户信息 - 示例路径:[server/src/modules/auth/auth.controller.ts:56](file://server/src/modules/auth/auth.controller.ts#L56) - 更新用户信息 - 示例路径:[server/src/modules/auth/auth.controller.ts:67-92](file://server/src/modules/auth/auth.controller.ts#L67-L92) - 权限检查(基于memberLevel) - 可在中间件中添加权限校验逻辑,参考类型定义:[server/src/types/index.ts:18](file://server/src/types/index.ts#L18) ### Token刷新机制建议 - 刷新流程 - 客户端持有access_token与refresh_token - access_token过期时,使用refresh_token向服务端申请新token - 服务端验证refresh_token有效性,签发新access_token并可更新refresh_token - 安全要点 - refresh_token应存储在安全容器中,定期轮换 - 服务端记录refresh_token使用日志,防止滥用