简介
本技术文档聚焦 DouPHP 的安全中间件体系,围绕以下目标展开:
- 解释安全中间件在 HTTP 边界的作用与实现原理,包括基线安全响应头下发、代理信任与 Host 校验等。
- 深入解析 AbstractSecurityHeadersMiddleware 抽象类的设计模式与安全头配置项。
- 说明前台、API、后台三端安全中间件的差异化注册与使用方式。
- 提供 CSP、X-Frame-Options、HSTS 等安全头的配置方法与最佳实践。
- 面向初学者阐明安全中间件的重要性;为高级开发者提供自定义安全策略的扩展指南。
项目结构
DouPHP 将“安全”能力以中间件形式嵌入到各模块的请求处理管道中,并通过统一的配置文件集中管理安全策略。关键位置如下:
- 核心抽象:位于 core/foundation/middleware 下的 AbstractSecurityHeadersMiddleware,负责统一下发基线安全响应头。
- 三端薄壳:admin、api、front 各自提供同名 SecurityHeadersMiddleware,继承核心抽象,行为一致但便于按端独立注册。
- 配置中心:config/security.php 集中定义可信代理、可信 Host、安全头、限流与会话硬化策略。
- 鉴权模式:各端 init/middleware.php 声明鉴权模式(public/optional/required),配合 UserAuth 中间件完成访问控制。
graph TB
A["请求进入"] --> B["前端路由匹配"]
B --> C["安全中间件<br/>AbstractSecurityHeadersMiddleware"]
C --> D["业务控制器"]
D --> E["响应返回"]
subgraph "配置"
F["config/security.php"]
end
F -.-> C
核心组件
- 抽象安全头中间件:AbstractSecurityHeadersMiddleware
- 职责:从配置读取 security.headers,并在响应头未发送前下发一组基线安全头;仅在 HTTPS 且显式开启时下发 HSTS。
- 关键点:仅对已匹配路由生效;404 由 Router 自渲染,不在覆盖范围。
- 三端安全头中间件薄壳:
- admin/middleware/SecurityHeadersMiddleware
- api/middleware/SecurityHeadersMiddleware
- front/middleware/SecurityHeadersMiddleware
- 职责:继承抽象类,保持行为一致,便于在各端路由管道中独立注册。
- 安全配置:config/security.php
- trusted_proxies:可信反向代理名单(精确 IP 或 CIDR)。空表示不信任任何代理,Request::ip() 仅用 REMOTE_ADDR。
- trusted_hosts:可信 Host 白名单(支持子域通配)。非空时未命中 Host 回落到首项,防止 Host 注入污染对外 URL。
- headers:基线安全响应头(不含 CSP);包含 X-Content-Type-Options、X-Frame-Options、Referrer-Policy、Permissions-Policy、HSTS。
- throttle:定向限流后端存储路径与默认策略。
- session:会话 Cookie 硬化(httponly、secure、samesite、use_strict_mode)。
架构总览
下图展示请求经过安全中间件并下发安全头的整体流程,以及配置如何驱动行为。
sequenceDiagram
participant Client as "客户端"
participant Router as "路由系统"
participant MW as "安全中间件<br/>AbstractSecurityHeadersMiddleware"
participant Ctrl as "业务控制器"
participant Resp as "HTTP 响应"
Client->>Router : "HTTP 请求"
Router->>MW : "进入中间件管道"
MW->>MW : "读取 config/security.php 的 headers"
MW->>Resp : "下发安全头如 X-Frame-Options、Referrer-Policy 等"
MW-->>Ctrl : "调用 next() 进入控制器"
Ctrl-->>Resp : "生成业务响应"
Resp-->>Client : "带安全头的响应"
详细组件分析
抽象安全头中间件(AbstractSecurityHeadersMiddleware)
- 设计要点
- 采用模板方法思想:handle 统一入口,sendHeaders 封装具体下发逻辑,子类可复用。
- 严格条件下发:仅在 headers_sent() 为 false 时写入响应头,避免重复或冲突。
- HSTS 条件:仅在 isSecure() 为真且配置启用时下发,避免在非 HTTPS 环境误发。
- 安全头映射
- content_type_options → X-Content-Type-Options: nosniff
- frame_options → X-Frame-Options
- referrer_policy → Referrer-Policy
- permissions_policy → Permissions-Policy
- hsts → Strict-Transport-Security(含 max-age 与 includeSubDomains 可选)
- 复杂度与性能
- 时间复杂度 O(1),空间复杂度 O(1)。
- 仅在管道前置执行一次,开销极低。
flowchart TD
Start(["进入 handle"]) --> ReadCfg["读取 security.headers"]
ReadCfg --> CheckSent{"headers 已发送?"}
CheckSent --> |是| Next["直接 next()"]
CheckSent --> |否| Send["sendHeaders()"]
Send --> CT["content_type_options?"]
CT --> |是| SetCT["设置 X-Content-Type-Options"]
CT --> |否| FO["frame_options?"]
SetCT --> FO
FO --> |是| SetFO["设置 X-Frame-Options"]
FO --> |否| RP["referrer_policy?"]
SetFO --> RP
RP --> |是| SetRP["设置 Referrer-Policy"]
RP --> |否| PP["permissions_policy?"]
SetRP --> PP
PP --> |是| SetPP["设置 Permissions-Policy"]
PP --> |否| HSTS["hsts 启用且 HTTPS?"]
SetPP --> HSTS
HSTS --> |是| SetHSTS["设置 Strict-Transport-Security"]
HSTS --> |否| End(["结束"])
SetHSTS --> End
Next --> End
三端安全头中间件薄壳
- admin/middleware/SecurityHeadersMiddleware
- api/middleware/SecurityHeadersMiddleware
- front/middleware/SecurityHeadersMiddleware
- 作用:通过命名空间隔离,便于在各端路由管道中独立注册与组合其他中间件(如认证、限流)。
代理信任与 Host 校验(基于配置)
- 可信代理(trusted_proxies)
- 目的:在负载均衡/Nginx 反代后,允许 Request::ip() 采信 X-Forwarded-* 等转发头。
- 建议:仅填入受控出口 IP 或网段(CIDR),生产环境务必最小化授权。
- 可信 Host(trusted_hosts)
- 目的:防止客户端伪造 Host 头污染对外 URL(邮件链接、跳转、缓存投毒)。
- 行为:非空时未命中 Host 回落到名单首项,避免错误域名外泄。
- 注意:当前代码中安全头中间件不直接读取 trusted_proxies/trusted_hosts;这些配置由 Init 早期合并入 Config,并在构造审计服务之前应用到 Request::setTrustedProxies(),确保后续 ip()/host() 调用正确。
前台与 API 模块的差异化管理
- 鉴权模式配置
- front/init/middleware.php:定义前台 auth_modes 与 work_required,决定哪些模块需登录、哪些可匿名或尝试恢复登录态。
- api/init/middleware.php:定义 API 端 auth_modes 与 work_required,强制新增模块必须显式登记,避免静默公开。
- 差异点
- 前台更侧重用户体验与会员增强展示(optional 较多)。
- API 端强调显式登记与最小权限原则,新增接口必须明确 public/optional/required。
依赖关系分析
- 组件耦合
- 三端 SecurityHeadersMiddleware 强依赖 AbstractSecurityHeadersMiddleware。
- AbstractSecurityHeadersMiddleware 依赖 Config 读取 security.headers。
- 安全头中间件与路由系统解耦:仅在命中路由时执行。
- 外部依赖
- Request::isSecure() 用于判断是否 HTTPS。
- request() helper 用于获取当前请求上下文。
classDiagram
class AbstractSecurityHeadersMiddleware {
+handle(next) mixed
-sendHeaders(headers) void
}
class Admin_SecurityHeadersMiddleware
class Api_SecurityHeadersMiddleware
class Front_SecurityHeadersMiddleware
class Config {
+get(key, default) mixed
}
class Request {
+isSecure() bool
}
Admin_SecurityHeadersMiddleware --|> AbstractSecurityHeadersMiddleware
Api_SecurityHeadersMiddleware --|> AbstractSecurityHeadersMiddleware
Front_SecurityHeadersMiddleware --|> AbstractSecurityHeadersMiddleware
AbstractSecurityHeadersMiddleware --> Config : "读取安全头配置"
AbstractSecurityHeadersMiddleware --> Request : "判断HTTPS"
性能考量
- 中间件执行时机:管道最前置,仅一次读取配置与写入响应头,O(1) 复杂度。
- 条件判断:仅在 headers_sent() 为 false 时写入,避免重复与额外开销。
- HSTS:仅在 HTTPS 且启用时下发,减少不必要头部。
- 建议:在生产环境开启 content_type_options、referrers-policy 与合理的 permissions-policy,提升安全性且几乎无性能影响。
故障排查指南
- 安全头未生效
- 检查是否在已匹配路由中触发(404 由 Router 自渲染,不在覆盖范围)。
- 确认 headers_sent() 未被提前输出(例如调试打印、BOM、空白字符)。
- 核对 config/security.php 的 headers 配置是否正确。
- HSTS 未下发
- 确认当前请求为 HTTPS(isSecure() 为真)。
- 确认 hsts.enabled 为 true。
- 代理信任问题导致 IP 不正确
- 检查 trusted_proxies 是否包含真实反向代理出口 IP/CIDR。
- 若为空,Request::ip() 仅使用 REMOTE_ADDR,不会采信 X-Forwarded-*。
- Host 头污染风险
- 配置 trusted_hosts 为非空白名单,避免未命中时回退到未知域名。
结论
DouPHP 的安全中间件体系通过“抽象基类 + 三端薄壳 + 集中配置”的方式,实现了统一、可配置、可扩展的 HTTP 安全策略落地。其核心价值在于:
- 统一下发基线安全头,降低各模块重复实现成本。
- 通过配置驱动安全策略,便于在不同环境灵活调整。
- 结合代理信任与 Host 校验,提升对现代部署拓扑的适配能力。
- 配合各端鉴权模式配置,形成完整的前置安全防护层。
附录:配置与使用示例
- 安全头配置(config/security.php)
- X-Frame-Options:frame_options 设置为 SAMEORIGIN 或 DENY,空串关闭。
- X-Content-Type-Options:content_type_options 为 true 时下发 nosniff。
- Referrer-Policy:referrer_policy 推荐 strict-origin-when-cross-origin。
- Permissions-Policy:permissions_policy 限制敏感能力(如摄像头、麦克风)。
- HSTS:hsts.enabled 为 true 且 HTTPS 时下发;max_age 建议较大值;subdomains 按需开启。
- 代理信任与 Host 校验
- trusted_proxies:填入可信反向代理出口 IP 或 CIDR,生产环境最小化授权。
- trusted_hosts:配置可信域名与子域通配,避免 Host 头注入污染对外 URL。
- 三端注册
- 在 front/api/admin 的路由管道中注册对应 SecurityHeadersMiddleware,即可自动应用安全头策略。
- 鉴权模式
- 在前台与 API 的 init/middleware.php 中为每个模块显式声明 public/optional/required,遵循最小权限原则。