You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

5.6 KiB

登录注册系统设计

日期: 2026/05/22 状态: 已批准,待实现


1. 核心架构:Strategy 模式

AuthService (统一入口)
  ├── PasswordStrategy   ← 现在实现
  └── OAuthStrategy     ← 接口预留,以后实现 Google/GitHub 等
  • AuthService 持有所有 Strategy 实例,通过 type 参数选择使用哪个 Strategy
  • IAuthStrategy 接口定义 authenticate()generateTokens()
  • 以后加 OAuth 只新增 GoogleStrategy extends OAuthStrategyAuthService 无需改动

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

// Request
{ "email": "user@example.com", "password": "Str0ng!", "username": "john" }

// Response 201
{ "user": { "id": 1, "email": "user@example.com", "username": "john" } }

POST /api/auth/login

// Request
{ "email": "user@example.com", "password": "Str0ng!" }

// Response 200
{
  "user": { "id": 1, "email": "...", "username": "john", "role": "user" },
  "accessToken": "<jwt>"
}
// RefreshToken  HTTP Only Cookie

POST /api/auth/logout

// Response 200
{ "success": true }

POST /api/auth/refresh

// Response 200(Cookie 自动发送)
{ "accessToken": "<new-jwt>" }

GET /api/auth/me

// Response 200
{ "user": { "id": 1, "email": "...", "username": "john", "role": "user" } }

错误响应格式

{ "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 预留接口

interface IAuthStrategy {
  readonly type: 'password' | 'oauth';
  authenticate(credentials: unknown): Promise<User>;
  generateTokens(user: User, sessionId: string): TokenPair;
  revokeSession(sessionId: string): Promise<void>;
}

abstract class OAuthStrategy implements IAuthStrategy {
  abstract readonly provider: 'google' | 'github' | string;
  abstract readonly type: 'oauth';

  abstract authenticate(oauthToken: string): Promise<User>;
  generateTokens(user: User, sessionId: string): TokenPair { /* ... */ }
  revokeSession(sessionId: string): Promise<void> { /* ... */ }
}

以后实现 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 客户端