# 用户认证系统 **本文引用的文件** - [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/config/index.ts](file://server/src/config/index.ts) - [server/src/types/index.ts](file://server/src/types/index.ts) - [server/src/models/index.ts](file://server/src/models/index.ts) - [server/prisma/schema.prisma](file://server/prisma/schema.prisma) - [server/src/middleware/errorHandler.ts](file://server/src/middleware/errorHandler.ts) - [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/app.ts](file://server/src/app.ts) - [deploy-package/server/modules/auth/auth.controller.js](file://deploy-package/server/modules/auth/auth.controller.js) - [deploy-package/server/modules/auth/auth.service.js](file://deploy-package/server/modules/auth/auth.service.js) ## 目录 1. [简介](#简介) 2. [项目结构](#项目结构) 3. [核心组件](#核心组件) 4. [架构总览](#架构总览) 5. [详细组件分析](#详细组件分析) 6. [依赖关系分析](#依赖关系分析) 7. [性能考量](#性能考量) 8. [故障排查指南](#故障排查指南) 9. [结论](#结论) 10. [附录](#附录) ## 简介 本技术文档面向“用户认证系统”,围绕手机号登录流程、JWT 令牌生成与验证机制、用户权限控制策略进行深入解析;同时覆盖认证中间件实现原理、Token 刷新机制与会话管理策略、用户注册流程、登录验证逻辑、密码加密存储、头像上传管理等能力,并提供完整的 API 接口文档、错误码说明、用户状态与权限分级、安全防护措施、常见问题解决方案与性能优化建议。 ## 项目结构 认证子系统主要由以下层次构成: - 控制层:处理 HTTP 请求与响应,负责参数校验、调用服务层并返回统一格式结果 - 服务层:封装业务逻辑,如短信验证码生成与校验、JWT 令牌签发、用户注册与登录、用户信息读取与更新 - 中间件层:认证中间件、可选认证中间件、安全中间件、限流中间件、错误处理中间件 - 配置层:JWT 秘钥、过期时间、上传目录大小等全局配置 - 数据层:Prisma 客户端与数据库模型定义(用户表等) ```mermaid graph TB subgraph "应用入口" APP["应用启动(app.ts)"] end subgraph "中间件层" ERR["错误处理(errorHandler.ts)"] SEC["安全中间件(security.ts)"] RL["限流中间件(rate-limiter.ts)"] AUTHMW["认证中间件(auth.ts)"] end subgraph "认证模块" CTRL["控制器(auth.controller.ts)"] SVC["服务(auth.service.ts)"] CFG["配置(config.ts)"] TYPES["类型(types.ts)"] MODELS["模型(models/index.ts)"] PRISMA["数据库(schema.prisma)"] end APP --> ERR APP --> SEC APP --> RL APP --> AUTHMW APP --> CTRL CTRL --> SVC SVC --> MODELS MODELS --> PRISMA SVC --> CFG AUTHMW --> CFG AUTHMW --> TYPES ``` 图表来源 - [server/src/app.ts:1-194](file://server/src/app.ts#L1-L194) - [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/middleware/auth.ts:1-81](file://server/src/middleware/auth.ts#L1-L81) - [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/config/index.ts:1-117](file://server/src/config/index.ts#L1-L117) - [server/src/types/index.ts:1-124](file://server/src/types/index.ts#L1-L124) - [server/src/models/index.ts:1-15](file://server/src/models/index.ts#L1-L15) - [server/prisma/schema.prisma:1-472](file://server/prisma/schema.prisma#L1-L472) 章节来源 - [server/src/app.ts:1-194](file://server/src/app.ts#L1-L194) - [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) ## 核心组件 - 认证控制器:提供发送验证码、手机号登录、获取用户信息、更新用户信息等接口 - 认证服务:封装验证码生成/校验、JWT 签发、用户注册/登录、用户信息查询 - 认证中间件:校验 Authorization 头与 JWT 有效性,注入用户上下文 - 安全中间件:XSS/SQL 注入防护与敏感数据脱敏 - 限流中间件:基于内存或 Redis 的限流策略,针对不同接口维度进行配额控制 - 错误处理中间件:统一捕获异常并返回标准化错误响应 - 配置中心:集中管理 JWT 秘钥、过期时间、上传大小等 - 类型系统:统一 JwtPayload、用户信息结构、会员配额等类型定义 - 数据模型:基于 Prisma 的用户表结构及索引 章节来源 - [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:1-117](file://server/src/config/index.ts#L1-L117) - [server/src/types/index.ts:1-124](file://server/src/types/index.ts#L1-L124) - [server/src/models/index.ts:1-15](file://server/src/models/index.ts#L1-L15) - [server/prisma/schema.prisma:1-472](file://server/prisma/schema.prisma#L1-L472) ## 架构总览 认证系统采用分层架构,请求从应用入口进入,依次经过中间件链路(错误处理、安全、限流),再由认证控制器接收,调用认证服务执行业务逻辑,最终通过 Prisma 访问数据库。 ```mermaid sequenceDiagram participant C as "客户端" participant A as "应用(app.ts)" participant M as "中间件链" participant R as "认证路由(auth.controller)" participant S as "认证服务(auth.service)" participant P as "Prisma(models)" participant D as "MySQL(schema)" C->>A : "HTTP 请求" A->>M : "中间件处理" M->>R : "路由转发" R->>S : "调用业务方法" S->>P : "查询/创建用户" P->>D : "执行 SQL" D-->>P : "返回结果" P-->>S : "用户数据" S-->>R : "登录结果(含token)" R-->>C : "统一响应" ``` 图表来源 - [server/src/app.ts:1-194](file://server/src/app.ts#L1-L194) - [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/models/index.ts:1-15](file://server/src/models/index.ts#L1-L15) - [server/prisma/schema.prisma:1-472](file://server/prisma/schema.prisma#L1-L472) ## 详细组件分析 ### 手机号登录流程 - 参数校验:手机号格式校验 - 验证码校验:开发环境可跳过,生产环境需校验验证码有效期与一致性 - 用户查找/创建:按手机号查找,不存在则创建默认用户 - JWT 签发:生成带用户标识与手机号的令牌,设置过期时间 - 返回结果:包含 token 与用户信息 ```mermaid flowchart TD Start(["开始"]) --> Validate["校验手机号格式"] Validate --> PhoneValid{"格式正确?"} PhoneValid -- "否" --> ErrFormat["抛出参数错误"] PhoneValid -- "是" --> DevCheck["开发环境免密登录?"] DevCheck --> |是| SkipVerify["跳过验证码校验"] DevCheck --> |否| VerifyCode["校验验证码(有效期/一致性)"] VerifyCode --> CodeOK{"验证码有效?"} CodeOK -- "否" --> ErrCode["抛出验证码错误"] CodeOK -- "是" --> FindOrCreate["查找或创建用户"] FindOrCreate --> CreateUser["创建默认用户(昵称/头像/等级)"] CreateUser --> GenToken["生成JWT(7天过期)"] VerifyCode --> GenToken SkipVerify --> GenToken GenToken --> Done(["返回token+用户信息"]) ErrFormat --> Done ErrCode --> Done ``` 图表来源 - [server/src/modules/auth/auth.controller.ts:32-52](file://server/src/modules/auth/auth.controller.ts#L32-L52) - [server/src/modules/auth/auth.service.ts:44-97](file://server/src/modules/auth/auth.service.ts#L44-L97) 章节来源 - [server/src/modules/auth/auth.controller.ts:32-52](file://server/src/modules/auth/auth.controller.ts#L32-L52) - [server/src/modules/auth/auth.service.ts:44-97](file://server/src/modules/auth/auth.service.ts#L44-L97) ### JWT 令牌生成与验证机制 - 生成:payload 包含 userId、phone,使用固定秘钥与 7 天过期时间 - 验证:从 Authorization 头解析 Bearer Token,使用相同秘钥验证签名与有效期 - 开发模式:可通过环境变量开关跳过认证,便于联调 ```mermaid sequenceDiagram participant S as "服务(auth.service)" participant J as "JWT库" participant MW as "中间件(auth.ts)" participant CL as "客户端" CL->>S : "登录(手机号+验证码)" S->>J : "sign(payload, secret, {expiresIn})" J-->>S : "token" S-->>CL : "返回token" CL->>MW : "携带Authorization : Bearer token" MW->>J : "verify(token, secret)" J-->>MW : "payload(含userId/phone)" MW-->>CL : "放行(注入ctx.state.user)" ``` 图表来源 - [server/src/modules/auth/auth.service.ts:34-41](file://server/src/modules/auth/auth.service.ts#L34-L41) - [server/src/middleware/auth.ts:7-49](file://server/src/middleware/auth.ts#L7-L49) - [server/src/config/index.ts:77-81](file://server/src/config/index.ts#L77-L81) 章节来源 - [server/src/modules/auth/auth.service.ts:34-41](file://server/src/modules/auth/auth.service.ts#L34-L41) - [server/src/middleware/auth.ts:7-49](file://server/src/middleware/auth.ts#L7-L49) - [server/src/config/index.ts:77-81](file://server/src/config/index.ts#L77-L81) ### 认证中间件实现原理 - 支持强制认证与可选认证两种模式 - 强制认证:必须携带合法 Bearer Token,否则抛出未授权错误 - 可选认证:若携带非法 Token,则回退为测试用户上下文 - 开发模式:可通过环境变量开关跳过认证 ```mermaid flowchart TD Enter(["进入中间件"]) --> CheckAuth["读取Authorization头"] CheckAuth --> HasHeader{"存在且格式正确?"} HasHeader -- "否" --> Optional{"是否可选认证?"} HasHeader -- "是" --> Parse["解析Bearer token"] Parse --> Verify["验证JWT(签名/过期)"] Verify --> Valid{"有效?"} Valid -- "是" --> Inject["注入ctx.state.user"] Valid -- "否" --> Optional Optional --> |可选| TestUser["注入测试用户(超级VIP)"] Optional --> |强制| Err["抛出未授权错误"] Inject --> Next["继续后续处理"] TestUser --> Next Err --> End(["结束"]) Next --> End ``` 图表来源 - [server/src/middleware/auth.ts:51-81](file://server/src/middleware/auth.ts#L51-L81) - [server/src/middleware/auth.ts:7-49](file://server/src/middleware/auth.ts#L7-L49) 章节来源 - [server/src/middleware/auth.ts:51-81](file://server/src/middleware/auth.ts#L51-L81) - [server/src/middleware/auth.ts:7-49](file://server/src/middleware/auth.ts#L7-L49) ### Token 刷新机制与会话管理策略 - 当前实现未提供 Token 刷新接口,JWT 默认 7 天过期 - 建议策略: - 引入 Refresh Token:登录成功返回 Access Token 与 Refresh Token - Access Token 短期有效(如 15 分钟),Refresh Token 长期有效(如 7 天) - 刷新接口:使用 Refresh Token 换取新的 Access Token - 会话管理:服务端记录 Refresh Token 并支持撤销(黑名单/白名单) - 安全增强:刷新时校验设备指纹、IP 地址变化触发二次校验 章节来源 - [server/src/modules/auth/auth.service.ts:34-41](file://server/src/modules/auth/auth.service.ts#L34-L41) - [server/src/config/index.ts:77-81](file://server/src/config/index.ts#L77-L81) ### 用户注册流程 - 若手机号对应的用户不存在,则创建默认用户(昵称、头像、会员等级、用量统计等字段初始化) - 新用户标记为“isNewUser”返回给前端 ```mermaid flowchart TD Start(["开始"]) --> FindUser["按手机号查找用户"] FindUser --> Exists{"是否存在?"} Exists -- "是" --> ReturnUser["返回现有用户"] Exists -- "否" --> Create["创建默认用户(昵称/头像/等级)"] Create --> ReturnUser ReturnUser --> End(["结束"]) ``` 图表来源 - [server/src/modules/auth/auth.service.ts:66-82](file://server/src/modules/auth/auth.service.ts#L66-L82) 章节来源 - [server/src/modules/auth/auth.service.ts:66-82](file://server/src/modules/auth/auth.service.ts#L66-L82) ### 登录验证逻辑 - 手机号格式校验 - 验证码校验(开发环境可跳过) - 用户查找/创建 - JWT 签发 - 统一响应包装 章节来源 - [server/src/modules/auth/auth.controller.ts:32-52](file://server/src/modules/auth/auth.controller.ts#L32-L52) - [server/src/modules/auth/auth.service.ts:44-97](file://server/src/modules/auth/auth.service.ts#L44-L97) ### 密码加密存储 - 当前系统采用手机号登录,未涉及明文密码存储 - 若引入账号密码体系,建议: - 使用强哈希算法(如 bcrypt、scrypt、argon2)存储密码 - 为每个用户生成唯一盐值 - 定期轮换密钥与哈希参数 章节来源 - [server/src/modules/auth/auth.service.ts:11-32](file://server/src/modules/auth/auth.service.ts#L11-L32) ### 头像上传管理 - 上传目录:由配置中心统一管理 - 上传大小限制:50MB(配置项) - 建议: - 对上传内容进行类型与大小校验 - 使用对象存储(OSS)替代本地磁盘 - 对头像进行缩略图生成与 CDN 加速 章节来源 - [server/src/config/index.ts:113-117](file://server/src/config/index.ts#L113-L117) - [server/src/app.ts:76-83](file://server/src/app.ts#L76-L83) ### 用户权限控制策略 - 会员等级:0(免费)、1(月度)、2(年度) - 会员配额:每日生成次数、单次字数上限 - 免费用户:较低配额 - 月度/年度用户:更高配额或无限制 - 限流策略:按用户等级差异化限流 章节来源 - [server/src/types/index.ts:18-124](file://server/src/types/index.ts#L18-L124) - [server/src/middleware/rate-limiter.ts:106-110](file://server/src/middleware/rate-limiter.ts#L106-L110) ### API 接口文档 - 发送验证码 - 方法与路径:POST /api/auth/send-code - 请求参数: - phone: string(必填,手机号格式校验) - 响应: - code: number(0 表示成功) - message: string - data: { phone, code } - 错误码:400(参数错误) - 手机号登录 - 方法与路径:POST /api/auth/login - 请求参数: - phone: string(必填) - code: string(非必填;开发环境可为空或特定值跳过校验) - 响应: - code: number(0 表示成功) - message: string - data: { token, user: { id, phone, nickname, avatar, memberLevel, isNewUser } } - 错误码:400(参数错误)、401(验证码错误或过期) - 获取用户信息 - 方法与路径:GET /api/auth/user-info - 请求头:Authorization: Bearer - 响应: - code: number(0 表示成功) - message: string - data: { id, phone, nickname, avatar, memberLevel, memberExpireAt, dailyUsage } - 错误码:401(未授权)、404(用户不存在) - 更新用户信息 - 方法与路径:PUT /api/auth/user-info - 请求头:Authorization: Bearer - 请求参数:nickname: string(可选)、avatar: string(可选) - 响应: - code: number(0 表示成功) - message: string - data: { nickname, avatar } - 错误码:400(用户不存在)、401(未授权) 章节来源 - [server/src/modules/auth/auth.controller.ts:10-92](file://server/src/modules/auth/auth.controller.ts#L10-L92) - [server/src/modules/auth/auth.service.ts:99-115](file://server/src/modules/auth/auth.service.ts#L99-L115) ## 依赖关系分析 ```mermaid classDiagram class AuthController { +sendCode() +login() +getUserInfo() +updateUserInfo() } class AuthService { +generateSmsCode() +verifySmsCode() +generateToken() +loginWithPhone() +getUserInfo() } class AuthMiddleware { +authMiddleware() +optionalAuth() } class ErrorHandler { +errorHandler() } class Security { +xssProtection() +sqlInjectionProtection() +sensitiveDataMasking() } class RateLimiter { +createRateLimiter() +apiRateLimiter() +loginRateLimiter() +smsRateLimiter() +ttsRateLimiter() +uploadRateLimiter() } class Config { +jwt.secret +jwt.expiresIn +upload.maxSize } class Types { +JwtPayload +MemberLevel +ApiResponse } class Prisma { +User } AuthController --> AuthService : "调用" AuthController --> AuthMiddleware : "使用" AuthController --> ErrorHandler : "使用" AuthController --> Config : "读取" AuthService --> Prisma : "查询/创建" AuthMiddleware --> Config : "读取" AuthMiddleware --> Types : "使用" Security --> ErrorHandler : "配合" RateLimiter --> Config : "读取" ``` 图表来源 - [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/config/index.ts:1-117](file://server/src/config/index.ts#L1-L117) - [server/src/types/index.ts:1-124](file://server/src/types/index.ts#L1-L124) - [server/src/models/index.ts:1-15](file://server/src/models/index.ts#L1-L15) 章节来源 - [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/config/index.ts:1-117](file://server/src/config/index.ts#L1-L117) - [server/src/types/index.ts:1-124](file://server/src/types/index.ts#L1-L124) - [server/src/models/index.ts:1-15](file://server/src/models/index.ts#L1-L15) ## 性能考量 - 限流策略:针对登录、验证码、TTS 生成、文件上传分别设置限流,避免滥用 - 缓存与降级:Redis 可用时优先使用 Redis 限流器,不可用时回退内存限流器 - 日志与监控:统一错误处理与性能监控中间件,结合 Sentry 进行错误追踪 - 上传优化:建议使用对象存储(OSS)替代本地磁盘,提升并发与可靠性 - 数据库:合理索引(手机号、OpenID 等)减少查询延迟 章节来源 - [server/src/middleware/rate-limiter.ts:1-120](file://server/src/middleware/rate-limiter.ts#L1-L120) - [server/src/app.ts:64-69](file://server/src/app.ts#L64-L69) - [server/src/app.ts:134-151](file://server/src/app.ts#L134-L151) ## 故障排查指南 - 未携带 Authorization 或格式错误 - 现象:返回未授权错误 - 处理:确认请求头格式为 Bearer Token - Token 已过期或无效 - 现象:返回 Token 已过期或无效 - 处理:引导用户重新登录获取新 Token - 验证码错误或过期 - 现象:登录失败 - 处理:重新发送验证码或检查验证码有效期 - 用户不存在 - 现象:更新用户信息时报错 - 处理:确认用户已登录并存在 - 参数错误 - 现象:返回参数错误 - 处理:检查手机号格式与必填字段 章节来源 - [server/src/middleware/auth.ts:22-48](file://server/src/middleware/auth.ts#L22-L48) - [server/src/modules/auth/auth.controller.ts:36-43](file://server/src/modules/auth/auth.controller.ts#L36-L43) - [server/src/modules/auth/auth.service.ts:22-32](file://server/src/modules/auth/auth.service.ts#L22-L32) - [server/src/middleware/errorHandler.ts:26-67](file://server/src/middleware/errorHandler.ts#L26-L67) ## 结论 本认证系统以手机号登录为核心,结合 JWT 实现轻量级身份认证,并通过中间件层提供安全与限流保障。当前未实现 Token 刷新与密码加密存储,建议在后续版本中引入 Refresh Token 与更强的密码安全策略;同时可迁移上传存储至对象存储并完善权限分级与配额控制,进一步提升安全性与可扩展性。 ## 附录 ### 数据模型(用户) ```mermaid erDiagram USER { int id PK string phone string openid string nickname string avatar int memberLevel datetime memberExpireAt int dailyUsage string lastUsageDate datetime createdAt datetime updatedAt } ``` 图表来源 - [server/prisma/schema.prisma:10-38](file://server/prisma/schema.prisma#L10-L38) ### 类型定义(关键) - JwtPayload:包含 userId、phone、iat、exp - MemberLevel:0 免费、1 月度、2 年度 - ApiResponse:统一响应结构(code/message/data) 章节来源 - [server/src/types/index.ts:66-89](file://server/src/types/index.ts#L66-L89) - [server/src/types/index.ts:18](file://server/src/types/index.ts#L18)