文档目录
内容安全策略(CSP)

简介

本文件为 DouPHP 提供内容安全策略(CSP)的落地配置与实施指南。当前代码已具备“基线安全响应头”中间件体系,但尚未内置 CSP 下发能力。本文在现有基础上,给出:

  • CSP 工作原理与 XSS 防护机制说明
  • 各指令作用与适用场景(default-src、script-src、style-src、img-src、connect-src、font-src、object-src、media-src、frame-src 等)
  • 严格模式与宽松模式的配置示例
  • nonce 与 hash 的使用方法与注意事项
  • CSP 报告机制的配置与监控建议
  • 常见错误与调试方法
  • 渐进式部署策略与兼容性考量

项目结构

DouPHP 的安全响应头由统一的基类中间件负责下发,三端(前台、后台、API)通过薄壳子类复用逻辑;安全相关配置集中在 config/security.php。模板中已包含 CSRF token,便于后续结合 CSP 进行更细粒度的脚本控制。

graph TB
A["请求进入"] --> B["前端中间件<br/>front/middleware/SecurityHeadersMiddleware.php"]
A --> C["后台中间件<br/>admin/middleware/SecurityHeadersMiddleware.php"]
A --> D["API中间件<br/>api/middleware/SecurityHeadersMiddleware.php"]
B --> E["基类中间件<br/>AbstractSecurityHeadersMiddleware.php"]
C --> E
D --> E
E --> F["读取配置<br/>config/security.php"]
E --> G["设置响应头<br/>X-Content-Type-Options / X-Frame-Options / Referrer-Policy / Permissions-Policy / HSTS"]
G --> H["业务控制器/视图渲染<br/>模板含csrf-token"]

核心组件

  • 安全配置中心:config/security.php 中的 security.headers 用于集中管理基线安全头(当前不含 CSP)。
  • 基线安全头中间件:AbstractSecurityHeadersMiddleware 统一读取配置并下发安全头,支持 HSTS 的条件下发。
  • 三端薄壳中间件:front/admin/api 下的 SecurityHeadersMiddleware 继承基类,确保不同入口行为一致。
  • 响应对象:Response.php 提供 setHeader/getHeader/send 等能力,可作为扩展点注入 CSP。

架构总览

下图展示从请求到响应头的完整路径,以及未来引入 CSP 的关键扩展点。

sequenceDiagram
participant U as "浏览器"
participant M as "三端中间件"
participant B as "基类中间件"
participant C as "配置中心"
participant R as "响应对象"
U->>M : 发起HTTP请求
M->>B : handle(next)
B->>C : 读取security.headers
C-->>B : 返回配置数组
B->>R : 设置X-Content-Type-Options等
Note over B,R : 可扩展在此处增加CSP头
B-->>U : 返回响应(含安全头)

详细组件分析

安全中间件与配置

  • 基类中间件负责根据配置下发安全头,并在 HTTPS 且开启时下发 HSTS。
  • 三端中间件为薄壳,保证前台、后台、API 行为一致。
  • 配置项 headers 目前包含 frame_options、content_type_options、referrer_policy、permissions_policy、hsts。

模板与CSRF上下文

  • 前台默认模板 index.dwt 与后台首页 admin/view/index.htm 均包含 csrf-token meta 标签,便于后续在脚本中校验或配合 CSP 使用。

CSP 指令说明与防护要点

  • default-src:未指定其他指令时的兜底策略,建议设置为 'self' 以最小化资源加载面。
  • script-src:控制可执行脚本来源。推荐仅允许 'self' 与必要 CDN;内联脚本需配合 nonce 或 hash。
  • style-src:控制样式来源。第三方 UI 库可能需额外域名;内联样式可使用 nonce。
  • img-src:控制图片来源。CDN、图标字体、Base64 图片需按需放开。
  • connect-src:控制 fetch/XHR/WebSocket 等网络请求目标。应限制为后端 API 与可信服务。
  • font-src:控制字体加载来源。CDN 或自托管字体需明确列出。
  • object-src:控制插件(如 &lt;object>/&lt;embed>)。现代站点通常设为 'none'。
  • media-src:控制音视频等资源。按需放开至 CDN 或自有媒体服务器。
  • frame-src:控制 iframe 来源。若无需嵌入页面,建议 'none';必要时限定可信域。
  • report-uri/report-to:用于上报被阻止的资源加载尝试,便于发现违规与逐步收紧策略。

严格模式与宽松模式配置示例

  • 严格模式(推荐生产环境)
    • 仅允许同源脚本与样式
    • 禁止 object-src
    • 限制 connect-src 到自有 API
    • 使用 nonce 放行必要的内联脚本
    • 启用 report-uri 或 report-to 收集违规报告
  • 宽松模式(开发/迁移期)
    • 允许 'unsafe-inline' 与 'unsafe-eval'(仅限过渡期)
    • 放宽 script-src/style-src/connect-src 至第三方域名
    • 尽快收敛到严格模式,避免长期保留宽松指令

注意:以上为策略思路示例,实际值需依据站点资源清单与第三方依赖确定。

nonce 与 hash 的使用方法与安全考虑

  • nonce:为每次请求生成一次性随机值,写入 &lt;script nonce="..."> 与 CSP 的 script-src 指令。服务端需在响应头中注入该 nonce。
  • hash:对特定内联脚本计算哈希值并加入 CSP,适用于静态内联脚本;维护成本较高,优先推荐 nonce。
  • 安全要点:
    • 每次请求必须重新生成 nonce,避免重用
    • 不要将 nonce 暴露给不受信任的上下文
    • 谨慎使用 'unsafe-inline'/'unsafe-eval',仅在迁移期临时使用

CSP 报告机制的配置与监控

  • 使用 report-uri 或 report-to 指定上报端点,接收浏览器发来的违规报告 JSON。
  • 建议:
    • 先以 report-only 模式运行,观察违规清单
    • 逐步收紧策略,移除不必要的宽松指令
    • 建立告警与看板,持续监控违规趋势

渐进式部署策略与兼容性考虑

  • 阶段一:report-only 模式上线,收集违规数据,不阻断正常功能
  • 阶段二:基于报告逐步收紧指令,优先处理高频违规
  • 阶段三:切换到严格模式,关闭 report-only
  • 兼容性:
    • 旧版浏览器可能忽略未知指令,不影响基本功能
    • 对于不支持 report-to 的环境,回退到 report-uri
    • 对第三方 SDK 进行适配(添加域名、改用外链脚本、替换内联逻辑)

依赖关系分析

  • 中间件依赖配置中心读取 security.headers
  • 三端中间件统一继承基类,保证行为一致
  • 响应对象提供设置响应头的能力,可用于扩展 CSP
classDiagram
class AbstractSecurityHeadersMiddleware {
+handle(next)
-sendHeaders(headers)
}
class FrontSecurityHeadersMiddleware
class AdminSecurityHeadersMiddleware
class ApiSecurityHeadersMiddleware
class Response {
+setHeader(name, value)
+getHeader(name)
+send()
}
FrontSecurityHeadersMiddleware --> AbstractSecurityHeadersMiddleware : "继承"
AdminSecurityHeadersMiddleware --> AbstractSecurityHeadersMiddleware : "继承"
ApiSecurityHeadersMiddleware --> AbstractSecurityHeadersMiddleware : "继承"
AbstractSecurityHeadersMiddleware --> Response : "设置响应头"

性能考虑

  • CSP 解析发生在浏览器侧,对服务器性能影响极小
  • report-only 模式可减少误报带来的运维压力
  • 合理拆分脚本与样式,减少内联,降低 nonce/hash 维护成本
  • 使用 CDN 缓存静态资源,提升首屏加载速度

故障排查指南

  • 常见问题
    • 脚本被阻止:检查 script-src 是否包含必要来源或 nonce
    • 样式加载失败:检查 style-src 与字体/图标来源
    • 接口调用失败:检查 connect-src 是否包含 API 域名
    • 报告为空:确认 report-uri/report-to 配置正确且可达
  • 调试步骤
    • 使用浏览器开发者工具的“控制台”查看被阻止的资源
    • 启用 report-only 模式,收集违规报告进行分析
    • 逐步收紧策略,定位具体违规指令
    • 核对模板与第三方库是否使用了内联脚本或动态 eval

结论

DouPHP 已具备完善的安全响应头中间件基础,建议在现有框架上扩展 CSP 能力:通过配置中心统一管理策略,利用中间件统一下发,并结合 report-only 模式实现渐进式收紧。最终目标是构建最小权限的资源加载策略,有效防御 XSS 攻击,同时保持系统兼容性与可维护性。

附录

  • 建议的 CSP 策略字段(供扩展参考)
    • default-src: 'self'
    • script-src: 'self' 与必要 CDN,内联脚本使用 nonce
    • style-src: 'self' 与必要 CDN,内联样式使用 nonce
    • img-src: 'self' 与必要 CDN
    • connect-src: 'self' 与 API 域名
    • font-src: 'self' 与必要 CDN
    • object-src: 'none'
    • media-src: 'self' 与必要 CDN
    • frame-src: 'none' 或受限域名
    • report-uri/report-to: 上报端点
添加日期:2026-10-05