简介
本文件面向 DouPHP 的安全配置与防护体系,围绕 config/security.php 中的安全栈配置展开,系统说明 CSRF 防护、XSS 防御(通过响应头与模板转义)、SQL 注入防护(参数化查询与输入过滤)、会话安全、访问控制、IP 白名单、请求频率限制等机制。同时解释安全中间件的工作原理与执行顺序,给出最佳实践与安全事件处理流程建议。
项目结构
DouPHP 将安全能力以“配置 + 中间件”的方式解耦:
- 配置层:config/security.php 集中定义可信代理、可信 Host、安全响应头、限流策略与会话 Cookie 硬化。
- 中间件层:各端(前台/后台/API)在 HTTP 边界通过中间件实现 CSRF、限流、安全头等横切关注点。
- 初始化层:各端 Init 类负责启动时加载配置、注册安全相关服务与门面,确保早期应用安全策略。
graph TB
A["请求进入"] --> B["安全响应头中间件<br/>AbstractSecurityHeadersMiddleware"]
B --> C["CSRF 校验后台<br/>CsrfMiddleware"]
B --> D["请求限流API<br/>ThrottleMiddleware"]
C --> E["业务控制器/服务"]
D --> E
E --> F["返回响应"]
图表来源
- core/foundation/middleware/AbstractSecurityHeadersMiddleware.php:41-80
- admin/middleware/CsrfMiddleware.php:47-79
- api/middleware/ThrottleMiddleware.php:64-88
章节来源
- config/security.php:51-86
- core/foundation/middleware/AbstractSecurityHeadersMiddleware.php:41-80
- admin/middleware/CsrfMiddleware.php:47-79
- api/middleware/ThrottleMiddleware.php:64-88
核心组件
- 安全配置中心:security.headers、trusted_proxies、trusted_hosts、throttle、session。
- 安全响应头中间件:统一下发 X-Content-Type-Options、X-Frame-Options、Referrer-Policy、Permissions-Policy,按需下发 HSTS。
- CSRF 中间件:后台基于静态令牌模型校验表单提交,支持特定路由的例外令牌与 GET 续跑场景。
- 限流中间件:API 端按 IP 对敏感写接口进行速率限制,超限返回 429。
- 会话安全:Cookie 的 HttpOnly、Secure、SameSite 与严格模式,防止会话劫持与固定攻击。
- 可信代理与 Host:Request::ip()/host() 在可信代理/Host 白名单下工作,避免伪造头污染 URL。
章节来源
- config/security.php:51-86
- core/foundation/middleware/AbstractSecurityHeadersMiddleware.php:41-80
- admin/middleware/CsrfMiddleware.php:47-79
- api/middleware/ThrottleMiddleware.php:38-88
架构总览
安全栈贯穿请求生命周期:
- 启动阶段:Init 调用 startSession() 应用会话安全配置;instantiateCommonFactories() 中根据 security.trusted_proxies 设置 Request 可信代理,保证后续 ip()/host() 正确。
- 管道阶段:安全响应头中间件最先下发基线安全头;后台管道包含 CSRF 中间件;API 管道包含限流中间件。
- 业务阶段:控制器与服务使用参数化查询与输入校验,结合模板自动转义降低 XSS 风险。
- 响应阶段:由安全头中间件保障响应头一致性,必要时由限流/CSRF 中间件拒绝非法请求。
sequenceDiagram
participant Client as "客户端"
participant SH as "安全响应头中间件"
participant CSRF as "后台CSRF中间件"
participant TH as "API限流中间件"
participant Biz as "业务控制器/服务"
Client->>SH : 发起请求
SH-->>Client : 下发安全头
alt 后台请求
SH->>CSRF : 校验令牌
CSRF-->>Biz : 通过或拒绝
else API请求
SH->>TH : 检查配额
TH-->>Biz : 通过或429
end
Biz-->>Client : 返回业务结果
图表来源
- core/foundation/middleware/AbstractSecurityHeadersMiddleware.php:41-80
- admin/middleware/CsrfMiddleware.php:47-79
- api/middleware/ThrottleMiddleware.php:64-88
详细组件分析
安全配置中心(config/security.php)
- trusted_proxies:可信反向代理列表(精确 IP 或 CIDR)。为空表示不信任任何代理,仅使用 REMOTE_ADDR。
- trusted_hosts:可信 Host 白名单(精确域名或子域通配)。非空时未命中 Host 回落到首项,防止 Host 头注入。
- headers:基线安全响应头(不含 CSP),包括 frame_options、content_type_options、referrer_policy、permissions_policy、hsts(enabled/max_age/subdomains)。
- throttle:定向限流存储目录与默认全局限流策略(null 表示默认不限流,仅敏感端点在中间件内限定额)。
- session:会话 Cookie 硬化(httponly、secure、samesite、use_strict_mode)。
章节来源
- config/security.php:51-86
安全响应头中间件(AbstractSecurityHeadersMiddleware)
- 作用:在管道最前置读取 security.headers,并下发 X-Content-Type-Options、X-Frame-Options、Referrer-Policy、Permissions-Policy;当 HTTPS 且 hsts.enabled=true 时下发 Strict-Transport-Security。
- 适用:三端薄壳子类(admin/api/front)继承该基类,行为一致。
flowchart TD
Start(["进入中间件"]) --> ReadCfg["读取 security.headers"]
ReadCfg --> CheckSent{"是否已发送头部?"}
CheckSent --> |是| Next["继续管道"]
CheckSent --> |否| Apply["下发安全头"]
Apply --> HSTS{"HTTPS 且启用HSTS?"}
HSTS --> |是| SetHSTS["设置 Strict-Transport-Security"]
HSTS --> |否| Next
SetHSTS --> Next
Next --> End(["结束"])
图表来源
- core/foundation/middleware/AbstractSecurityHeadersMiddleware.php:41-80
章节来源
- core/foundation/middleware/AbstractSecurityHeadersMiddleware.php:41-80
后台 CSRF 防护(CsrfMiddleware)
- 令牌模型:登录成功后下发共享静态令牌 static_admin;表单页渲染 token,提交时中间件自动校验。
- 豁免与例外:部分路由通过声明式 withoutMiddleware 豁免;找回密码等匿名流程使用一次性 password_reset 令牌;备份/导入/报表导出等 GET 续跑链接也校验。
- 失败处理:抛出 DomainException,由后台入口捕获后走统一提示页,引导刷新或重新登录。
sequenceDiagram
participant Admin as "后台页面"
participant CSRF as "CsrfMiddleware"
participant Ctrl as "控制器"
Admin->>Admin : 渲染表单并嵌入token
Admin->>CSRF : POST 提交表单
CSRF->>CSRF : 校验令牌(静态/一次性)
alt 校验通过
CSRF-->>Ctrl : 放行
Ctrl-->>Admin : 处理成功
else 校验失败
CSRF-->>Admin : 抛出异常(页面过期/非法)
end
图表来源
- admin/middleware/CsrfMiddleware.php:47-79
章节来源
- admin/middleware/CsrfMiddleware.php:24-79
API 请求限流(ThrottleMiddleware)
- 目标接口:登录、注册、手机登录、找回密码、短信验证码、公共匿名写接口(留言/咨询/邮件订阅)、防伪查询、LLM 成本端点等。
- 策略:按 IP 统计窗口期内请求次数,超限返回 JSON 429,并附带 Retry-After。
- 扩展:可在 $limits 中新增路由键与配额,快速接入新的高频写接口保护。
flowchart TD
Req["收到API请求"] --> Match["匹配路由键到配额"]
Match --> Found{"找到配额?"}
Found --> |否| Pass["放行至业务"]
Found --> |是| Count["统计IP窗口计数"]
Count --> Over{"超过限额?"}
Over --> |否| Pass
Over --> |是| Reject["返回429并终止"]
Pass --> End["结束"]
Reject --> End
图表来源
- api/middleware/ThrottleMiddleware.php:38-88
章节来源
- api/middleware/ThrottleMiddleware.php:25-88
会话安全与可信代理/Host
- 会话 Cookie 硬化:httponly=true 防 JS 窃取 sid;secure=null 跟随 IS_HTTPS;samesite=Lax 防跨站 CSRF;use_strict_mode=true 拒绝未初始化外部 sid。
- 可信代理:trusted_proxies 为空则忽略 X-Forwarded-*,仅用 REMOTE_ADDR;部署在 Nginx/负载均衡时需填入代理出口 IP。
- 可信 Host:trusted_hosts 非空时未命中 Host 回落首项,避免对外 URL 被污染。
章节来源
- config/security.php:51-86
密码加密策略与访问控制
- 密码重置令牌:生成随机 token,存储其哈希值并设置过期时间,避免明文泄露。
- 访问控制:API 端通过 UserAuthMiddleware 解析 Authorization 头并注入用户上下文;后台通过 AuthMiddleware 与 PermissionMiddleware 控制角色与权限。
- 数据访问:控制器/服务中使用参数化查询与类型转换,减少 SQL 注入风险。
章节来源
- api/init/Init.php:237-253
- admin/init/Init.php:129-179
依赖关系分析
- 配置依赖:安全头中间件依赖 Config::get('security.headers');限流中间件依赖配置 store 路径与默认策略。
- 中间件协作:安全头中间件优先于 CSRF/限流;CSRF 与限流互不干扰,分别作用于不同端。
- 初始化依赖:Init 在 early stage 应用会话安全与可信代理,确保后续 Request 方法行为正确。
graph LR
SecCfg["security.php"] --> SH["安全响应头中间件"]
SecCfg --> TH["限流中间件"]
InitA["admin/init/Init.php"] --> SecCfg
InitB["api/init/Init.php"] --> SecCfg
SH --> Admin["后台管道"]
SH --> Api["API管道"]
CSRF["后台CSRF中间件"] --> Admin
TH --> Api
图表来源
- config/security.php:51-86
- core/foundation/middleware/AbstractSecurityHeadersMiddleware.php:41-80
- admin/middleware/CsrfMiddleware.php:47-79
- api/middleware/ThrottleMiddleware.php:64-88
- admin/init/Init.php:129-179
- api/init/Init.php:127-189
章节来源
- config/security.php:51-86
- core/foundation/middleware/AbstractSecurityHeadersMiddleware.php:41-80
- admin/middleware/CsrfMiddleware.php:47-79
- api/middleware/ThrottleMiddleware.php:64-88
- admin/init/Init.php:129-179
- api/init/Init.php:127-189
性能考虑
- 安全头中间件仅在命中路由时运行,避免对 404 等非业务路径产生额外开销。
- 限流中间件按 IP 与窗口计数,建议使用高性能存储后端(当前为文件后端),在高并发场景可替换为 Redis 等内存存储以降低 I/O。
- 会话严格模式可减少无效 sid 带来的额外校验成本。
故障排查指南
- CSRF 失败:常见原因为页面停留过久导致令牌失效或重新登录后令牌旋转。应引导用户刷新页面或重新登录。
- 限流触发:检查 API 端高频写接口是否达到配额;必要时调整 ThrottleMiddleware::$limits 中的 window 与 max。
- 安全头未生效:确认中间件已挂载到管道且 headers_sent() 前调用;检查 security.headers 配置是否正确。
- 会话问题:确认 httponly/secure/samesite/use_strict_mode 配置符合部署环境;HTTPS 环境下 secure 建议跟随 IS_HTTPS。
章节来源
- admin/middleware/CsrfMiddleware.php:68-79
- api/middleware/ThrottleMiddleware.php:75-88
- core/foundation/middleware/AbstractSecurityHeadersMiddleware.php:41-80
- config/security.php:79-85
结论
DouPHP 的安全体系以配置为中心、中间件为执行载体,覆盖 CSRF、XSS、SQL 注入、会话安全、访问控制、限流与响应头加固等关键领域。通过合理配置 security.php 与在各端挂载对应中间件,可在不侵入业务代码的前提下获得一致的安全保障。建议在生产环境开启 HSTS、严格会话策略,并对高频写接口实施限流,配合审计日志与告警提升可观测性。
附录
- 安全头配置建议:
- 启用 X-Content-Type-Options 与 X-Frame-Options(SAMEORIGIN/DENY)。
- 设置 Referrer-Policy 为 strict-origin-when-cross-origin。
- 在 HTTPS 且启用 HSTS 时设置合理的 max_age 与 includeSubDomains。
- 敏感信息保护:
- 不在日志中记录敏感字段(如密码、令牌)。
- 使用环境变量或受控配置文件管理密钥,避免硬编码。
- HTTPS 配置:
- 全站强制 HTTPS;启用 HSTS 并逐步扩大范围。
- 在反向代理层关闭不必要的协议与加密套件。
- 安全日志与监控告警:
- 记录 CSRF 失败、限流触发、认证失败等安全事件。
- 对异常峰值与错误率设置阈值告警,及时处置潜在攻击。