用户认证系统.md 19 KB

用户认证系统

本文档引用的文件

  • server/src/modules/auth/auth.controller.ts
  • server/src/modules/auth/auth.service.ts
  • server/src/middleware/auth.ts
  • server/src/middleware/auth.js
  • server/src/middleware/security.ts
  • server/src/middleware/rate-limiter.ts
  • server/src/middleware/errorHandler.ts
  • server/src/config/index.ts
  • server/src/models/index.ts
  • server/src/types/index.ts
  • server/src/app.ts
  • 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载荷、响应体等类型声明

    graph TB
    App["应用入口<br/>server/src/app.ts"] --> Cfg["配置中心<br/>server/src/config/index.ts"]
    App --> Sec["安全中间件<br/>server/src/middleware/security.ts"]
    App --> Lim["限流中间件<br/>server/src/middleware/rate-limiter.ts"]
    App --> Err["错误处理中间件<br/>server/src/middleware/errorHandler.ts"]
    App --> AuthCtrl["认证控制器<br/>server/src/modules/auth/auth.controller.ts"]
    AuthCtrl --> AuthSvc["认证服务<br/>server/src/modules/auth/auth.service.ts"]
    AuthCtrl --> AuthMW["认证中间件<br/>server/src/middleware/auth.ts"]
    AuthSvc --> Types["类型定义<br/>server/src/types/index.ts"]
    AuthSvc --> Models["数据模型<br/>server/src/models/index.ts"]
    AuthMW --> Cfg
    AuthMW --> Err
    Sec --> App
    Lim --> App
    Err --> App
    

图表来源

  • server/src/app.ts:57-130
  • server/src/modules/auth/auth.controller.ts:1-94
  • server/src/modules/auth/auth.service.ts:1-115
  • server/src/middleware/auth.ts:1-81
  • server/src/middleware/security.ts:1-154
  • server/src/middleware/rate-limiter.ts:1-120
  • server/src/middleware/errorHandler.ts:1-67
  • server/src/config/index.ts:69-81
  • server/src/models/index.ts:1-15
  • server/src/types/index.ts:66-82

章节来源

  • server/src/app.ts:57-130

核心组件

  • 认证控制器:提供 /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
  • server/src/modules/auth/auth.service.ts:1-115
  • server/src/middleware/auth.ts:1-81
  • server/src/middleware/security.ts:1-154
  • server/src/middleware/rate-limiter.ts:1-120
  • server/src/middleware/errorHandler.ts:1-67
  • server/src/config/index.ts:69-81
  • server/src/models/index.ts:1-15
  • server/src/types/index.ts:66-82

架构总览

认证系统采用分层架构,控制器负责HTTP接口,服务层封装业务逻辑,中间件负责横切关注点(安全、限流、认证),配置与模型提供基础设施支撑。

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
  • server/src/modules/auth/auth.service.ts:11-97

详细组件分析

认证控制器分析

  • 接口职责
    • 发送验证码:校验手机号格式,生成并返回验证码(开发环境总是返回)
    • 手机号登录:校验手机号格式,支持免验证码登录(开发环境或特定code)
    • 用户信息:通过认证中间件获取当前用户ID,查询用户信息
    • 更新用户信息:通过认证中间件获取当前用户ID,更新昵称/头像
  • 控制器与中间件协作:使用 authMiddleware 保护受保护接口,将用户信息写入 ctx.state.user

    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

章节来源

  • server/src/modules/auth/auth.controller.ts:1-94

认证服务分析

  • 验证码机制
    • 生成:4位数字验证码,存储于Map,5分钟过期
    • 校验:检查是否存在、是否过期、是否匹配,匹配后删除
  • JWT签发
    • 载荷包含 userId、phone
    • 使用固定密钥与7天过期时间
  • 登录/注册流程

    • 免验证码登录:开发环境或code为特定值时跳过校验
    • 查找用户,不存在则创建默认用户
    • 生成token并返回用户信息

      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
  • server/src/config/index.ts:77-81
  • server/src/models/index.ts:1-15

章节来源

  • server/src/modules/auth/auth.service.ts:1-115

认证中间件分析

  • 开发环境开关:通过环境变量控制是否启用认证
  • Authorization头解析:Bearer Token格式校验
  • JWT验证:使用固定密钥验证token有效性,区分过期与无效错误
  • 可选认证:optionalAuth在无token或token无效时,降级为测试用户

    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
  • server/src/middleware/auth.js:44-94

章节来源

  • server/src/middleware/auth.ts:1-81
  • server/src/middleware/auth.js:1-137

安全中间件分析

  • XSS防护:递归清理请求体与查询参数中的危险字符,设置安全响应头
  • SQL注入防护:检测请求参数中的常见注入模式,拦截非法请求
  • 敏感数据脱敏:对响应体中的敏感字段进行脱敏处理

章节来源

  • server/src/middleware/security.ts:1-154

限流中间件分析

  • 限流器选择:优先使用Redis,不可用时回退到内存限流器
  • 场景化限流:
    • API全局限流:每分钟100次
    • 登录接口限流:每分钟5次,封禁5分钟
    • 验证码发送限流:每分钟1次,每小时5次
    • TTS/上传限流:按用户维度限流
  • 错误响应:429状态码,包含retry-after提示

章节来源

  • server/src/middleware/rate-limiter.ts:1-120
  • server/src/services/redis.service.js:232-325

错误处理与类型系统

  • 统一错误处理:捕获异常,按环境输出详细或简要信息
  • 自定义错误类型:AppError、UnauthorizedError、ForbiddenError、NotFoundError、BadRequestError、QuotaExceededError
  • 类型系统:JwtPayload、IUser、ApiResponse等类型约束

章节来源

  • server/src/middleware/errorHandler.ts:1-67
  • server/src/types/index.ts:66-82

配置与数据模型

  • 配置中心:JWT密钥与过期时间、模型配置等
  • 数据模型:Prisma客户端连接数据库,提供用户CRUD能力

章节来源

  • server/src/config/index.ts:69-81
  • server/src/models/index.ts:1-15

依赖关系分析

认证系统各组件之间的依赖关系如下:

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
  • server/src/modules/auth/auth.service.ts:1-115
  • server/src/middleware/auth.ts:1-81
  • server/src/middleware/errorHandler.ts:1-67
  • server/src/middleware/security.ts:1-154
  • server/src/middleware/rate-limiter.ts:1-120
  • server/src/app.ts:26-128

章节来源

  • server/src/app.ts:26-128

性能考虑

  • 限流策略:针对高频接口(登录、验证码、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
  • server/src/middleware/rate-limiter.ts:60-71
  • server/src/middleware/errorHandler.ts:3-24

结论

本认证系统以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
  • 读取当前用户信息
    • 示例路径:server/src/modules/auth/auth.controller.ts:56
  • 更新用户信息
    • 示例路径:server/src/modules/auth/auth.controller.ts:67-92
  • 权限检查(基于memberLevel)
    • 可在中间件中添加权限校验逻辑,参考类型定义:server/src/types/index.ts:18

Token刷新机制建议

  • 刷新流程
    • 客户端持有access_token与refresh_token
    • access_token过期时,使用refresh_token向服务端申请新token
    • 服务端验证refresh_token有效性,签发新access_token并可更新refresh_token
  • 安全要点
    • refresh_token应存储在安全容器中,定期轮换
    • 服务端记录refresh_token使用日志,防止滥用