# 登录注册系统设计 **日期:** 2026/05/22 **状态:** 已批准,待实现 --- ## 1. 核心架构:Strategy 模式 ``` AuthService (统一入口) ├── PasswordStrategy ← 现在实现 └── OAuthStrategy ← 接口预留,以后实现 Google/GitHub 等 ``` - `AuthService` 持有所有 Strategy 实例,通过 `type` 参数选择使用哪个 Strategy - `IAuthStrategy` 接口定义 `authenticate()` 和 `generateTokens()` - 以后加 OAuth 只新增 `GoogleStrategy extends OAuthStrategy`,`AuthService` 无需改动 --- ## 2. 数据表扩展 ### users 表扩展字段 | 字段 | 类型 | 说明 | |---|---|---| | `email` | text | unique,加索引 | | `emailVerified` | integer (bool) | 邮箱是否验证 | | `passwordHistory` | text (JSON) | 最近 5 个密码 hash,防复用 | | `failedLoginAttempts` | integer | 连续失败次数 | | `lockoutUntil` | integer (timestamp) | 锁定截止时间 | | `lastLoginAt` | integer (timestamp) | 最后登录时间 | | `lastLoginIp` | text | 最后登录 IP | | `refreshToken` | text | 当前 refresh token hash(兼容旧字段) | ### user_sessions 表(新建) | 字段 | 类型 | 说明 | |---|---|---| | `id` | text | session id (uuid) | | `userId` | integer | 外键 references users.id | | `refreshTokenHash` | text | token hash(bcrypt) | | `userAgent` | text | 浏览器 UA | | `ip` | text | 登录 IP | | `createdAt` | integer (timestamp_ms) | 创建时间 | | `expiresAt` | integer (timestamp_ms) | 过期时间 | | `revokedAt` | integer (timestamp_ms) | 撤销时间,nullable | --- ## 3. 安全机制 ### 密码 - bcrypt 加密,cost factor 12 - 注册:密码强度校验(8位以上,大小写+数字+特殊字符) - 登录失败 5 次锁定 15 分钟 - 密码历史:最近 5 个密码不允许复用 ### Token - Access Token:JWT,15 分钟有效期,payload 含 userId + sessionId + role - Refresh Token:UUIDv4,7 天有效期,存储 hash 到 user_sessions - Refresh Token 放 HTTP Only + Secure + SameSite=Strict Cookie - Refresh Token Rotation:每次 refresh 颁发新 token,旧 token 作废 ### 登录安全 - 记录 lastLoginAt / lastLoginIp - 失败次数累计 + 锁定机制 - 通用限流:同一 IP 1 分钟内最多 5 次登录尝试(所有 auth 路由共享) --- ## 4. API 路由 ``` POST /api/auth/register 注册 POST /api/auth/login 登录 POST /api/auth/logout 登出 POST /api/auth/refresh 刷新 token GET /api/auth/me 获取当前用户 ``` ### 请求响应格式 **POST /api/auth/register** ```json // Request { "email": "user@example.com", "password": "Str0ng!", "username": "john" } // Response 201 { "user": { "id": 1, "email": "user@example.com", "username": "john" } } ``` **POST /api/auth/login** ```json // Request { "email": "user@example.com", "password": "Str0ng!" } // Response 200 { "user": { "id": 1, "email": "...", "username": "john", "role": "user" }, "accessToken": "" } // RefreshToken 放 HTTP Only Cookie ``` **POST /api/auth/logout** ```json // Response 200 { "success": true } ``` **POST /api/auth/refresh** ```json // Response 200(Cookie 自动发送) { "accessToken": "" } ``` **GET /api/auth/me** ```json // Response 200 { "user": { "id": 1, "email": "...", "username": "john", "role": "user" } } ``` ### 错误响应格式 ```json { "error": { "code": "INVALID_CREDENTIALS", "message": "邮箱或密码错误" } } ``` 错误码: - `INVALID_CREDENTIALS` — 登录失败 - `ACCOUNT_LOCKED` — 账户锁定 - `WEAK_PASSWORD` — 密码强度不足 - `EMAIL_EXISTS` — 邮箱已注册 - `TOKEN_EXPIRED` — access token 过期 - `SESSION_REVOKED` — session 已撤销 --- ## 5. 目录结构 ``` server/ ├── api/auth/ │ ├── register.post.ts │ ├── login.post.ts │ ├── logout.post.ts │ ├── refresh.post.ts │ └── me.get.ts ├── service/auth/ │ ├── index.ts ← AuthService │ ├── strategies/ │ │ ├── index.ts ← StrategyRegistry │ │ ├── password.strategy.ts │ │ └── oauth.strategy.ts ← 抽象类预留 │ └── lib/ │ ├── jwt.ts │ ├── password.ts │ └── rate-limit.ts ├── middleware/ │ └── auth.ts ← 请求认证中间件 └── types/ └── auth.ts ``` --- ## 6. OAuth2 预留接口 ```typescript interface IAuthStrategy { readonly type: 'password' | 'oauth'; authenticate(credentials: unknown): Promise; generateTokens(user: User, sessionId: string): TokenPair; revokeSession(sessionId: string): Promise; } abstract class OAuthStrategy implements IAuthStrategy { abstract readonly provider: 'google' | 'github' | string; abstract readonly type: 'oauth'; abstract authenticate(oauthToken: string): Promise; generateTokens(user: User, sessionId: string): TokenPair { /* ... */ } revokeSession(sessionId: string): Promise { /* ... */ } } ``` 以后实现 OAuth 时: 1. 新增 `GoogleStrategy extends OAuthStrategy` 2. 在 `StrategyRegistry` 注册 `google: new GoogleStrategy()` 3. `AuthService` 无需改动 --- ## 7. 实现顺序 1. Schema 迁移(users 字段扩展 + user_sessions 表) 2. `PasswordStrategy` 实现(密码加密、校验、历史) 3. `AuthService` + Strategy 模式 4. API 路由(注册、登录、登出、刷新、获取用户) 5. 中间件 + JWT 验证 6. 限流 + 锁定机制 7. 测试覆盖 --- ## 8. 依赖组件(已有) - bcryptjs — 密码加密 - Zod — 输入校验 - drizzle-orm — 数据库 ORM - @libsql/client — SQLite 客户端