用户认证系统
本文引用的文件
- server/src/modules/auth/auth.controller.ts
- server/src/modules/auth/auth.service.ts
- server/src/middleware/auth.ts
- server/src/config/index.ts
- server/src/types/index.ts
- server/src/models/index.ts
- server/prisma/schema.prisma
- server/src/middleware/errorHandler.ts
- server/src/middleware/security.ts
- server/src/middleware/rate-limiter.ts
- server/src/app.ts
- deploy-package/server/modules/auth/auth.controller.js
- deploy-package/server/modules/auth/auth.service.js
目录
- 简介
- 项目结构
- 核心组件
- 架构总览
- 详细组件分析
- 依赖关系分析
- 性能考量
- 故障排查指南
- 结论
- 附录
简介
本技术文档面向“用户认证系统”,围绕手机号登录流程、JWT 令牌生成与验证机制、用户权限控制策略进行深入解析;同时覆盖认证中间件实现原理、Token 刷新机制与会话管理策略、用户注册流程、登录验证逻辑、密码加密存储、头像上传管理等能力,并提供完整的 API 接口文档、错误码说明、用户状态与权限分级、安全防护措施、常见问题解决方案与性能优化建议。
项目结构
认证子系统主要由以下层次构成:
- 控制层:处理 HTTP 请求与响应,负责参数校验、调用服务层并返回统一格式结果
- 服务层:封装业务逻辑,如短信验证码生成与校验、JWT 令牌签发、用户注册与登录、用户信息读取与更新
- 中间件层:认证中间件、可选认证中间件、安全中间件、限流中间件、错误处理中间件
- 配置层:JWT 秘钥、过期时间、上传目录大小等全局配置
数据层:Prisma 客户端与数据库模型定义(用户表等)
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
- server/src/middleware/errorHandler.ts:1-67
- server/src/middleware/security.ts:1-154
- server/src/middleware/rate-limiter.ts:1-120
- server/src/middleware/auth.ts:1-81
- server/src/modules/auth/auth.controller.ts:1-94
- server/src/modules/auth/auth.service.ts:1-115
- server/src/config/index.ts:1-117
- server/src/types/index.ts:1-124
- server/src/models/index.ts:1-15
- server/prisma/schema.prisma:1-472
章节来源
- server/src/app.ts:1-194
- server/src/modules/auth/auth.controller.ts:1-94
- server/src/modules/auth/auth.service.ts:1-115
核心组件
- 认证控制器:提供发送验证码、手机号登录、获取用户信息、更新用户信息等接口
- 认证服务:封装验证码生成/校验、JWT 签发、用户注册/登录、用户信息查询
- 认证中间件:校验 Authorization 头与 JWT 有效性,注入用户上下文
- 安全中间件:XSS/SQL 注入防护与敏感数据脱敏
- 限流中间件:基于内存或 Redis 的限流策略,针对不同接口维度进行配额控制
- 错误处理中间件:统一捕获异常并返回标准化错误响应
- 配置中心:集中管理 JWT 秘钥、过期时间、上传大小等
- 类型系统:统一 JwtPayload、用户信息结构、会员配额等类型定义
- 数据模型:基于 Prisma 的用户表结构及索引
章节来源
- 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:1-117
- server/src/types/index.ts:1-124
- server/src/models/index.ts:1-15
- server/prisma/schema.prisma:1-472
架构总览
认证系统采用分层架构,请求从应用入口进入,依次经过中间件链路(错误处理、安全、限流),再由认证控制器接收,调用认证服务执行业务逻辑,最终通过 Prisma 访问数据库。
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
- server/src/modules/auth/auth.controller.ts:1-94
- server/src/modules/auth/auth.service.ts:1-115
- server/src/models/index.ts:1-15
- server/prisma/schema.prisma:1-472
详细组件分析
手机号登录流程
图表来源
- server/src/modules/auth/auth.controller.ts:32-52
- server/src/modules/auth/auth.service.ts:44-97
章节来源
- server/src/modules/auth/auth.controller.ts:32-52
- server/src/modules/auth/auth.service.ts:44-97
JWT 令牌生成与验证机制
- 生成:payload 包含 userId、phone,使用固定秘钥与 7 天过期时间
- 验证:从 Authorization 头解析 Bearer Token,使用相同秘钥验证签名与有效期
开发模式:可通过环境变量开关跳过认证,便于联调
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
- server/src/middleware/auth.ts:7-49
- server/src/config/index.ts:77-81
章节来源
- server/src/modules/auth/auth.service.ts:34-41
- server/src/middleware/auth.ts:7-49
- server/src/config/index.ts:77-81
认证中间件实现原理
图表来源
- server/src/middleware/auth.ts:51-81
- server/src/middleware/auth.ts:7-49
章节来源
- server/src/middleware/auth.ts:51-81
- server/src/middleware/auth.ts:7-49
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
- server/src/config/index.ts:77-81
用户注册流程
图表来源
- server/src/modules/auth/auth.service.ts:66-82
章节来源
- server/src/modules/auth/auth.service.ts:66-82
登录验证逻辑
- 手机号格式校验
- 验证码校验(开发环境可跳过)
- 用户查找/创建
- JWT 签发
- 统一响应包装
章节来源
- server/src/modules/auth/auth.controller.ts:32-52
- server/src/modules/auth/auth.service.ts:44-97
密码加密存储
- 当前系统采用手机号登录,未涉及明文密码存储
- 若引入账号密码体系,建议:
- 使用强哈希算法(如 bcrypt、scrypt、argon2)存储密码
- 为每个用户生成唯一盐值
- 定期轮换密钥与哈希参数
章节来源
- server/src/modules/auth/auth.service.ts:11-32
头像上传管理
- 上传目录:由配置中心统一管理
- 上传大小限制:50MB(配置项)
- 建议:
- 对上传内容进行类型与大小校验
- 使用对象存储(OSS)替代本地磁盘
- 对头像进行缩略图生成与 CDN 加速
章节来源
- server/src/config/index.ts:113-117
- server/src/app.ts:76-83
用户权限控制策略
- 会员等级:0(免费)、1(月度)、2(年度)
- 会员配额:每日生成次数、单次字数上限
- 免费用户:较低配额
- 月度/年度用户:更高配额或无限制
- 限流策略:按用户等级差异化限流
章节来源
- server/src/types/index.ts:18-124
- server/src/middleware/rate-limiter.ts:106-110
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
- server/src/modules/auth/auth.service.ts:99-115
依赖关系分析
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
- 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/config/index.ts:1-117
- server/src/types/index.ts:1-124
- server/src/models/index.ts:1-15
章节来源
- 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/config/index.ts:1-117
- server/src/types/index.ts:1-124
- server/src/models/index.ts:1-15
性能考量
- 限流策略:针对登录、验证码、TTS 生成、文件上传分别设置限流,避免滥用
- 缓存与降级:Redis 可用时优先使用 Redis 限流器,不可用时回退内存限流器
- 日志与监控:统一错误处理与性能监控中间件,结合 Sentry 进行错误追踪
- 上传优化:建议使用对象存储(OSS)替代本地磁盘,提升并发与可靠性
- 数据库:合理索引(手机号、OpenID 等)减少查询延迟
章节来源
- server/src/middleware/rate-limiter.ts:1-120
- server/src/app.ts:64-69
- server/src/app.ts:134-151
故障排查指南
- 未携带 Authorization 或格式错误
- 现象:返回未授权错误
- 处理:确认请求头格式为 Bearer Token
- Token 已过期或无效
- 现象:返回 Token 已过期或无效
- 处理:引导用户重新登录获取新 Token
- 验证码错误或过期
- 现象:登录失败
- 处理:重新发送验证码或检查验证码有效期
- 用户不存在
- 现象:更新用户信息时报错
- 处理:确认用户已登录并存在
- 参数错误
- 现象:返回参数错误
- 处理:检查手机号格式与必填字段
章节来源
- server/src/middleware/auth.ts:22-48
- server/src/modules/auth/auth.controller.ts:36-43
- server/src/modules/auth/auth.service.ts:22-32
- server/src/middleware/errorHandler.ts:26-67
结论
本认证系统以手机号登录为核心,结合 JWT 实现轻量级身份认证,并通过中间件层提供安全与限流保障。当前未实现 Token 刷新与密码加密存储,建议在后续版本中引入 Refresh Token 与更强的密码安全策略;同时可迁移上传存储至对象存储并完善权限分级与配额控制,进一步提升安全性与可扩展性。
附录
数据模型(用户)
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
类型定义(关键)
- JwtPayload:包含 userId、phone、iat、exp
- MemberLevel:0 免费、1 月度、2 年度
- ApiResponse:统一响应结构(code/message/data)
章节来源
- server/src/types/index.ts:66-89
- server/src/types/index.ts:18