简介
本文件为 DouPHP 的 API 安全控制文档,聚焦以下目标:
- API 认证机制:API 密钥管理、JWT 令牌验证与 OAuth 集成思路。
- 请求签名验证流程:参数签名算法与时间戳校验。
- 速率限制与防刷:IP 限流、用户限流、接口限流策略。
- API 版本控制与向后兼容。
- 敏感数据加密传输与响应脱敏。
- API 访问监控与安全审计。
说明:本文所有实现细节均基于仓库中已存在的中间件、入口与配置;对尚未内置的能力(如 OAuth)提供可落地的集成建议与接入点。
项目结构
DouPHP 的 API 子系统位于 api 目录,采用“入口 → 路由 → 中间件 → 控制器”的分层组织。安全相关能力集中在中间件与全局安全配置中:
- 入口:统一异常处理、路由分发与响应发送。
- 中间件:用户鉴权、定向限流、安全响应头。
- 配置:可信代理、Host 白名单、限流存储路径、会话 Cookie 硬化等。
graph TB
A["客户端"] --> B["API 入口<br/>api/index.php"]
B --> C["路由分发"]
C --> D["鉴权中间件<br/>UserAuthMiddleware"]
C --> E["限流中间件<br/>ThrottleMiddleware"]
C --> F["安全响应头中间件<br/>SecurityHeadersMiddleware"]
D --> G["业务控制器"]
E --> G
F --> G
G --> H["服务/模型"]
核心组件
- 用户鉴权中间件:从 Authorization: Bearer <token> 提取令牌,交由 auth('api') 解析登录态,并注入上下文;未登录或无工作端身份时返回 401/403。
- 定向限流中间件:按模块/动作/子控制器维度配置 IP 级限流配额,超限返回 429 并附带 Retry-After。
- 安全响应头中间件:下发基线安全响应头(X-Frame-Options、X-Content-Type-Options、Referrer-Policy、Permissions-Policy、HSTS)。
- 安全配置:可信代理、可信 Host、限流存储路径、会话 Cookie 硬化策略。
- 鉴权模式配置:按模块/动作声明 public/optional/required,以及 work_required 叠加的工作端身份校验。
架构总览
API 请求在入口进入后,先设置路由字符串,再执行 Init 引导与路由分发。鉴权与限流以中间件形式挂载,最终由控制器处理业务逻辑并返回 JSON 响应。
sequenceDiagram
participant C as "客户端"
participant I as "API 入口<br/>api/index.php"
participant R as "路由"
participant M1 as "鉴权中间件"
participant M2 as "限流中间件"
participant M3 as "安全响应头"
participant Ctrl as "控制器"
C->>I : HTTP 请求
I->>R : 设置路由并分发
R->>M1 : 尝试解析登录态
alt 需要登录
M1-->>C : 401/403未登录/无工作端身份
else 允许匿名或可选
M1-->>R : 通过
end
R->>M2 : 按模块/动作匹配限流规则
alt 超限
M2-->>C : 429 + Retry-After
else 未超限
M2-->>R : 通过
end
R->>M3 : 设置安全响应头
M3-->>Ctrl : 继续
Ctrl-->>C : JSON 响应
详细组件分析
用户鉴权与令牌验证
- 令牌来源:Authorization: Bearer <token>,通过 Request::bearerToken() 获取。
- 解析流程:调用 auth('api')->resolveUserContext(token),将结果 hydrate 到当前请求上下文。
- 策略:
- required:必须登录,否则 401。
- optional:尝试解析,失败不拦截。
- public:不尝试解析。
- work_required:在 required 基础上额外校验工作端身份,否则 403。
- 鉴权模式配置:在 api/init/middleware.php 中以 module/module/action/module/sub/action 粒度声明。
flowchart TD
Start(["进入鉴权中间件"]) --> Mode{"鉴权模式"}
Mode --> |public| Skip["跳过解析"] --> Next["放行"]
Mode --> |optional| Try["尝试解析 token"]
Mode --> |required| Try
Try --> Ok{"解析成功?"}
Ok --> |否| Reject401["返回 401"]
Ok --> |是| WorkCheck{"是否 work_required?"}
WorkCheck --> |否| Next
WorkCheck --> |是| HasWork{"存在工作端身份?"}
HasWork --> |否| Reject403["返回 403"]
HasWork --> |是| Next
Next --> End(["继续后续中间件/控制器"])
定向限流与防刷
- 限流范围:登录、注册、短信验证码、找回密码、公共匿名写接口(留言/咨询/邮件订阅)、防伪查询、LLM 成本端点等。
- 规则粒度:module/action/sub 组合键,命中即应用对应 max/window 配额。
- 行为:超限返回 429,并在响应头携带 Retry-After。
- 存储:限流状态写入 config/security.php 配置的 throttle.store 目录。
flowchart TD
S(["请求进入"]) --> Match["匹配模块/动作/子段"]
Match --> Found{"命中限流规则?"}
Found --> |否| Pass["放行"]
Found --> |是| Check["统计窗口内次数"]
Check --> Over{"超过阈值?"}
Over --> |是| Throttle["返回 429 + Retry-After"]
Over --> |否| Pass
Pass --> E(["结束"])
Throttle --> E
安全响应头与传输安全
- 响应头:X-Frame-Options、X-Content-Type-Options、Referrer-Policy、Permissions-Policy、HSTS(仅在 HTTPS 且启用时)。
- 可信代理与 Host:通过 security.trusted_proxies 与 security.trusted_hosts 控制真实 IP 与 Host 判定,防止伪造。
- 会话 Cookie:httponly、secure、samesite、use_strict_mode 等加固项。
API 版本控制与向后兼容
- 现状:代码库未发现显式的 API 版本路由前缀或版本协商逻辑。
- 建议实践:
- 使用 URL 前缀 v1/v2 区分版本,配合路由表集中管理。
- 在鉴权/限流配置中按版本维度扩展规则。
- 通过响应头 X-API-Version 标识版本,便于客户端适配。
- 废弃字段保留过渡期,并通过日志告警逐步下线。
请求签名验证与时间戳校验
- 现状:仓库未包含统一的请求签名与时间戳校验中间件。
- 建议实现要点:
- 签名参数:method、path、query_string、body_hash、timestamp、nonce、app_key。
- 签名算法:HMAC-SHA256(app_secret, sorted_params)。
- 时间戳窗口:服务端校验 timestamp 与当前时间差(如 ±5 分钟),拒绝过期请求。
- 防重放:nonce 去重缓存(Redis/内存),短 TTL。
- 接入点:作为前置中间件,在鉴权之前执行;失败返回 400/401。
- 与现有鉴权结合:签名通过后,再走 UserAuthMiddleware 进行用户/工作端身份校验。
API 密钥管理与 JWT/OAuth 集成
- 现状:
- 用户鉴权通过 Authorization: Bearer 令牌与 auth('api') 解析登录态。
- 未发现独立的 API Key 管理或 OAuth 授权码流程。
- 建议方案:
- API Key:为第三方系统分配 app_key/app_secret,用于签名与审计追踪。
- JWT:若需跨域/微服务共享会话,可在 auth('api') 层签发/校验 JWT,支持刷新令牌与黑名单。
- OAuth 2.0:新增 /oauth/token 与 /authorize 端点,支持授权码模式;结合现有用户体系发放 access_token。
- 权限模型:work_required 可扩展为细粒度资源/操作级权限。
敏感数据加密传输与响应脱敏
- 传输加密:强制 HTTPS,开启 HSTS;利用安全响应头降低风险面。
- 敏感字段:
- 输入侧:严格校验与过滤,避免注入。
- 输出侧:对身份证、手机号、邮箱、金额等敏感字段进行掩码或移除。
- 日志脱敏:确保日志不记录明文敏感信息。
- 建议:在控制器或统一响应格式化层集中脱敏。
访问监控与安全审计
- 现状:入口对未捕获异常进行错误日志记录。
- 建议增强:
- 统一访问日志:记录 method、path、ip、user_id、耗时、状态码、UA。
- 安全事件:登录失败、限流触发、鉴权失败、异常堆栈摘要。
- 指标上报:QPS、P95/P99 延迟、错误率、限流比率。
- 审计追踪:关键写操作的 before/after 快照与责任人。
依赖关系分析
- 入口依赖路由与 Init,Init 加载安全配置与中间件。
- 鉴权中间件依赖 auth('api') 与 Request 提供的 bearerToken。
- 限流中间件依赖配置中的 throttle.store 与抽象限流基类。
- 安全响应头中间件依赖抽象基类与 security.headers 配置。
graph LR
Entry["api/index.php"] --> Router["路由"]
Router --> AuthMW["UserAuthMiddleware"]
Router --> ThrottleMW["ThrottleMiddleware"]
Router --> SecHeaderMW["SecurityHeadersMiddleware"]
AuthMW --> Config["config/security.php"]
ThrottleMW --> Config
SecHeaderMW --> Config
性能考虑
- 限流存储:throttle.store 默认落盘,高并发场景建议迁移至 Redis/Memcached 以降低 IO 压力。
- 鉴权解析:auth('api') 解析 token 可能涉及数据库或缓存,建议引入本地缓存与连接池。
- 响应头:安全响应头开销极低,无需优化。
- 日志与审计:异步写入,避免阻塞主流程。
故障排查指南
- 401 未登录:检查 Authorization 头是否正确传递,鉴权模式是否为 required。
- 403 无工作端身份:确认 work_required 配置与用户是否具备工作端身份。
- 429 限流:核对模块/动作是否命中限流规则,适当放宽或优化客户端重试策略。
- 500 服务器错误:查看入口未捕获异常的日志输出,定位异常堆栈。
- Host/IP 问题:检查 trusted_proxies/trusted_hosts 配置,确保反向代理环境正确识别真实 IP。
结论
DouPHP 的 API 安全已具备基础而实用的能力:基于 Bearer 令牌的鉴权、按模块/动作的定向限流、安全响应头与会话硬化。建议在现有基础上补充请求签名、版本控制、OAuth/JWT 扩展、响应脱敏与审计监控,形成更完整的安全闭环。
附录
- 快速配置清单
- 启用 HTTPS 并开启 HSTS。
- 配置 trusted_proxies 与 trusted_hosts。
- 按需调整各模块的 auth_modes 与 work_required。
- 根据业务调整限流配额与存储后端。
- 在控制器或响应层集中脱敏敏感字段。
- 增加访问日志与安全审计埋点。