文档目录
API认证机制

简介

本文件面向DouPHP的API认证机制,聚焦以下目标:

  • Bearer Token认证流程:Token生成、存储与验证
  • 令牌结构与有效期管理:基于不透明随机token的生命周期与刷新策略
  • API密钥管理方案:第三方凭据的生成、权限绑定与安全存储
  • OAuth集成指南:以微信小程序登录为例,说明第三方登录流程与用户信息同步
  • 认证中间件配置与使用:按模块/动作粒度控制public/optional/required与工作端校验
  • 常见认证错误处理:未登录、无工作端身份、频率限制、账号锁定等

项目结构

API认证相关代码主要分布在以下位置:

  • 中间件层:API端会员鉴权中间件与通用骨架
  • Guard门面:API端Guard负责从请求头解析Bearer token并注入上下文
  • 服务层:API Token签发、解析、吊销;微信登录控制器;凭据加密服务
  • 客户端:小程序端本地持久化token与状态
graph TB
A["客户端<br/>小程序/前端"] --> B["API入口<br/>index.php"]
B --> C["路由分发"]
C --> D["中间件链<br/>UserAuthMiddleware"]
D --> E["API Guard<br/>Auth::resolveUserContext()"]
E --> F["Token服务<br/>ApiTokenService"]
F --> G["数据库<br/>user_token / user / user_sns"]
D --> H["业务控制器<br/>WeixinController等"]

核心组件

  • API认证中间件:从Authorization头提取Bearer token,调用Guard解析登录态,按配置决定放行或拒绝
  • API Guard门面:实现GuardContract,提供checkLoginState、resolveUserContext、hydrate等方法
  • API Token服务:负责不透明随机token的签发、解析、吊销与过期清理
  • 微信登录控制器:小程序code换取session_key,完成用户绑定/注册、发放token
  • 凭据加密服务:对第三方API密钥进行加密存储与解密读取

架构总览

API认证采用“中间件 + Guard + Token服务”的分层设计:

  • 中间件负责HTTP边界鉴权策略决策(public/optional/required)与工作端校验
  • Guard负责将Bearer token解析为会员上下文(userId、userProfile、workId)
  • Token服务负责凭证生命周期管理(签发、解析、吊销、过期清理)
  • 业务控制器在已鉴权上下文中执行业务逻辑
sequenceDiagram
participant C as "客户端"
participant M as "UserAuthMiddleware"
participant G as "API Guard(Auth)"
participant T as "ApiTokenService"
participant DB as "数据库"
participant Ctrl as "业务控制器"
C->>M : "携带 Authorization : Bearer <token>"
M->>G : "resolveUserContext(token)"
G->>T : "resolve(token)"
T->>DB : "查询 user_token (token_hash, expires_at)"
DB-->>T : "命中则返回 user_id"
T-->>G : "返回 user_id"
G->>DB : "读取 user / work 信息"
DB-->>G : "返回上下文"
G-->>M : "ok + userId + workId"
M->>Ctrl : "注入上下文后放行"
Ctrl-->>C : "业务响应"

详细组件分析

Bearer Token认证流程

  • 客户端在登录后保存服务端下发的token,并在后续请求中通过Authorization: Bearer &lt;token>发送
  • 中间件从请求头抽取token,交由Guard解析
  • Guard调用Token服务校验token有效性(格式、哈希匹配、过期时间),命中后构建用户上下文并注入
  • 若模式为required且未登录,返回401;若需要工作端身份但缺失,返回403
flowchart TD
Start(["请求进入"]) --> Extract["提取 Bearer Token"]
Extract --> Resolve["Guard解析上下文"]
Resolve --> Valid{"Token有效?"}
Valid -- 否 --> Mode{"鉴权模式"}
Mode -- required --> Reject401["返回 401 未登录"]
Mode -- optional --> Next["放行(匿名)"]
Mode -- public --> Next
Valid -- 是 --> Inject["注入用户上下文"]
Inject --> WorkCheck{"需要工作端?"}
WorkCheck -- 是 --> HasWork{"有工作端身份?"}
HasWork -- 否 --> Reject403["返回 403 无工作端权限"]
HasWork -- 是 --> Next
WorkCheck -- 否 --> Next
Next --> End(["继续处理"])

Token生成、存储与验证机制

  • 生成:登录成功后由Token服务签发不透明随机token(64位十六进制),仅下发一次明文
  • 存储:服务端仅存储token的sha256哈希、过期时间、最后活跃时间、客户端IP等元数据
  • 验证:每次请求时计算传入token的哈希,精确匹配数据库记录,同时检查过期时间与心跳更新
  • 吊销:支持单设备登出与全局登出(按用户ID删除所有token)
classDiagram
class ApiTokenService {
+issue(userId, ip) string
+resolve(token) int
+revoke(token) void
+revokeAllForUser(userId) void
}
class AuthFacade {
+checkLoginState(token) array
+resolveUserContext(token) array
+hydrate(context) void
}
class UserAuthMiddleware {
+resolveContext() array
+inject(context) void
+rejectUnauthenticated() void
+rejectForbidden() void
}
AuthFacade --> ApiTokenService : "使用"
UserAuthMiddleware --> AuthFacade : "调用"

令牌结构与有效期管理、刷新策略

  • 令牌结构:不透明随机token(64位十六进制),服务端仅存哈希,避免泄露可逆风险
  • 有效期:默认30天(TTL常量),过期即失效;解析时自动清理过期行
  • 刷新策略:建议客户端在接近过期前主动刷新(重新登录或调用刷新接口),服务端支持多设备并存(同一用户多条有效记录)

API密钥管理方案(第三方凭据)

  • 生成:在后台或初始化流程中生成第三方平台所需的API Key/Secret
  • 权限绑定:将密钥与提供方(provider)及配置项关联,必要时附加访问范围或配额
  • 安全存储:使用凭据加密服务对敏感字段(如api_key、config)进行加密写入;读取时按需解密
  • 迁移兼容:支持旧密钥格式迁移至当前站点密钥体系,确保平滑升级
flowchart TD
Gen["生成第三方密钥"] --> Encrypt["凭据加密(Cipher)"]
Encrypt --> Store["写入数据库(ai_key)"]
Use["业务调用(AiGateway)"] --> Decrypt["读取并解密"]
Decrypt --> Call["调用第三方API"]

OAuth集成指南(微信小程序登录)

  • 流程概述:小程序获取code → 后端用code换取session_key → 根据openid/unionid查找或创建用户 → 签发API token → 返回用户信息与鉴权标志
  • 用户信息同步:可选绑定手机号、记录推广关系、更新登录次数
  • 错误处理:code无效、unionid缺失、账户锁定、绑定异常等均有明确日志与提示
sequenceDiagram
participant WX as "微信开放平台"
participant MP as "小程序"
participant API as "WeixinController"
participant U as "用户服务"
participant T as "Token服务"
MP->>WX : "wx.login() 获取 code"
MP->>API : "GET /user/weixin/login?code=..."
API->>WX : "jscode2session(code)"
WX-->>API : "openid/unionid/session_key"
API->>U : "查找/创建用户"
U-->>API : "user_id"
API->>T : "issue(user_id, ip)"
T-->>API : "token"
API-->>MP : "{user : {user_id, token}, dou : {auth : {is_work}}}"

认证中间件的配置与使用

  • 配置方式:在API中间件配置文件中声明各模块/动作的鉴权模式(public/optional/required)与工作端要求列表
  • 规则优先级:路由级覆盖 > 模块/子模块/动作匹配 > 默认回退
  • 使用示例:新增API模块必须在auth_modes中显式登记,否则会被扫描工具拦截,防止新模块以匿名形态上线

客户端Token持久化与使用

  • 小程序端在登录后将token与user_id写入本地存储,后续请求统一带上Authorization头
  • 登出时清除本地缓存并重置状态
  • 首次加载时可恢复本地token用于预检登录态

依赖关系分析

  • 中间件依赖Guard门面进行上下文解析
  • Guard门面依赖Token服务进行凭证校验
  • 微信登录控制器依赖用户服务与Token服务完成登录与发牌
  • 凭据加密服务被AI网关等模块用于敏感配置的安全读写
graph LR
M["UserAuthMiddleware"] --> G["API Guard(Auth)"]
G --> T["ApiTokenService"]
W["WeixinController"] --> U["UserService"]
W --> T
A["AiGateway"] --> C["CredentialCipher"]

性能考虑

  • Token解析侧使用哈希匹配与恒定时间比较,避免时序攻击
  • 解析命中后按60秒节流更新last_active,减少频繁写库
  • 签发时清理过期token行,防止表膨胀
  • 中间件按模块/动作粒度配置,避免不必要的鉴权开销

故障排查指南

  • 未登录(401):检查Authorization头是否携带有效token;确认token未过期;确认鉴权模式是否为required
  • 无工作端权限(403):确认该模块是否在work_required列表中;确认当前用户具备工作端身份
  • 频率限制:登录接口存在IP频率限制,短时间内多次失败会触发限流
  • 账号锁定:连续失败会导致账户临时锁定,需等待解锁时间后再试
  • 微信登录异常:检查appid/appsecret配置;确认unionid获取成功;关注绑定异常日志

结论

DouPHP的API认证机制以中间件为核心,结合Guard门面与Token服务,实现了清晰、可扩展的Bearer Token认证流程。通过细粒度的鉴权模式配置与工作端校验,既能满足公开接口与私有接口的差异化需求,又能保障关键业务的安全性。配合小程序端的本地持久化与微信OAuth登录流程,形成了完整的移动端认证闭环。第三方凭据通过加密服务安全存储,提升了整体系统的安全性与可维护性。

附录

  • 推荐实践
    • 客户端在token即将过期前主动刷新,提升用户体验
    • 对所有敏感接口启用required模式,并对涉及工作端数据的接口启用work_required
    • 定期审计鉴权覆盖率,确保新增模块正确登记
    • 对第三方密钥实施最小权限原则与轮换策略
添加日期:2026-10-05