简介
本文件为 DouPHP 的 Referrer-Policy 安全响应头配置指南。内容涵盖:
- 各策略值的作用与差异(no-referrer、no-referrer-when-downgrade、origin、origin-when-cross-origin、same-origin、strict-origin、strict-origin-when-cross-origin、unsafe-url)
- 引用信息泄露的安全风险与隐私保护需求
- 不同业务场景下的推荐配置(表单提交、第三方集成等)
- 与 CSP 中 referrer 指令的关系
- 兼容性与测试方法
- 在 DouPHP 中的具体落地位置与修改方式
项目结构
DouPHP 通过“中间件 + 配置”的方式统一下发基线安全响应头,其中包含 Referrer-Policy。关键路径如下:
- 配置入口:config/security.php 中的 security.headers.referrer_policy
- 中间件基类:core/foundation/middleware/AbstractSecurityHeadersMiddleware.php
- 三端薄壳中间件:front/admin/api 下的 SecurityHeadersMiddleware.php(继承基类)
- HTML 标签级 referrerpolicy 支持:core/infra/security/Xss.php(允许 a/img/area/iframe 等标签携带 referrerpolicy 属性)
graph TB
A["请求进入"] --> B["前端/后台/API 路由匹配"]
B --> C["SecurityHeadersMiddleware(前端/后台/API)"]
C --> D["AbstractSecurityHeadersMiddleware.handle()"]
D --> E["读取 config/security.php 的 security.headers"]
E --> F{"referrer_policy 是否设置?"}
F -- 是 --> G["发送 Referrer-Policy 响应头"]
F -- 否 --> H["不发送该头"]
G --> I["继续处理请求"]
H --> I
核心组件
- 配置项 security.headers.referrer_policy:控制是否下发以及下发的 Referrer-Policy 值。空串表示关闭该响应头。
- 中间件基类 AbstractSecurityHeadersMiddleware:在管道最前置读取配置并发送一组基线安全响应头(含 Referrer-Policy)。
- 三端薄壳中间件:分别位于 front/admin/api,行为一致,仅继承基类。
- XSS 白名单:允许在 a/img/area/iframe 等标签上设置 referrerpolicy 属性,用于页面内细粒度覆盖。
架构总览
Referrer-Policy 在 DouPHP 中的生效流程:
- 请求命中路由后,进入对应端的 SecurityHeadersMiddleware。
- 调用基类的 handle(),读取 security.headers。
- 若 referrer_policy 非空,则发送 Referrer-Policy 响应头。
- 后续控制器/视图渲染时,HTML 标签可继续使用 referrerpolicy 进行更细粒度的覆盖(如特定链接或图片)。
sequenceDiagram
participant U as "浏览器"
participant MW as "SecurityHeadersMiddleware(前端/后台/API)"
participant BASE as "AbstractSecurityHeadersMiddleware"
participant CFG as "Config(security.headers)"
participant S as "服务端处理器"
U->>MW : HTTP 请求
MW->>BASE : handle(next)
BASE->>CFG : 读取 security.headers
alt referrer_policy 已设置
BASE-->>U : 响应头 Referrer-Policy : <值>
else 未设置
BASE-->>U : 不发送 Referrer-Policy
end
BASE-->>S : 继续处理请求
S-->>U : 业务响应
详细组件分析
配置层:config/security.php
- 位置:security.headers.referrer_policy
- 默认值:strict-origin-when-cross-origin
- 行为:
- 设置为空字符串时,中间件不会下发 Referrer-Policy 响应头。
- 设置为其他合法策略值时,将按该值下发。
中间件层:AbstractSecurityHeadersMiddleware
- 作用:在管道最前置下发基线安全响应头(包括 Referrer-Policy)。
- 关键点:
- 仅在 headers_sent() 之前执行,避免重复或失败。
- 仅对已匹配路由生效;404 由 Router 自渲染,不在中间件覆盖范围内。
- 同时下发 X-Content-Type-Options、X-Frame-Options、Permissions-Policy、HSTS(HTTPS+enabled)。
三端薄壳中间件
- front/middleware/SecurityHeadersMiddleware.php
- admin/middleware/SecurityHeadersMiddleware.php
- api/middleware/SecurityHeadersMiddleware.php
- 说明:三者均继承基类,行为一致,便于按端复用同一套安全头策略。
标签级覆盖:XSS 白名单中的 referrerpolicy
- 支持在 a、img、area、iframe 等标签上使用 referrerpolicy 属性,实现页面内细粒度控制。
- 适用场景:
- 某些外链需要放宽策略以获取必要引用信息。
- 敏感资源希望进一步收紧到 no-referrer。
依赖关系分析
- 中间件依赖配置:AbstractSecurityHeadersMiddleware 从 Config 读取 security.headers.referrer_policy。
- 三端中间件依赖基类:front/admin/api 的 SecurityHeadersMiddleware 均继承基类,共享逻辑。
- 页面级能力依赖 XSS 白名单:允许在特定标签使用 referrerpolicy 属性。
classDiagram
class AbstractSecurityHeadersMiddleware {
+handle(next)
-sendHeaders(headers)
}
class FrontSecurityHeadersMiddleware
class AdminSecurityHeadersMiddleware
class ApiSecurityHeadersMiddleware
class Config {
+get(key, default)
}
FrontSecurityHeadersMiddleware --> AbstractSecurityHeadersMiddleware : "继承"
AdminSecurityHeadersMiddleware --> AbstractSecurityHeadersMiddleware : "继承"
ApiSecurityHeadersMiddleware --> AbstractSecurityHeadersMiddleware : "继承"
AbstractSecurityHeadersMiddleware --> Config : "读取 security.headers"
性能与兼容性
- 性能影响:Referrer-Policy 响应头下发开销极低,几乎无性能影响。
- 兼容性:
- 现代浏览器普遍支持 Referrer-Policy。
- 旧版浏览器会忽略未知策略值,因此不建议使用非法值。
- 若需完全禁用该头,可将 referrer_policy 设为空串。
- 与 HSTS 的关系:HSTS 仅在 HTTPS 且 enabled 时下发,不影响 Referrer-Policy 的行为。
故障排查
- 现象:响应头未出现 Referrer-Policy
- 检查 config/security.php 中 security.headers.referrer_policy 是否为空串。
- 确认请求命中了路由(404 由 Router 自渲染,不在中间件覆盖范围)。
- 确认未在更早阶段输出响应头导致 headers_sent() 为真。
- 现象:部分链接仍泄露完整 URL
- 检查页面中是否存在 referrerpolicy 属性覆盖了全局策略。
- 针对特定外链或敏感资源,可在相应标签上设置更严格的 referrerpolicy。
- 现象:第三方脚本或 SDK 无法获取必要引用
- 评估是否需要放宽策略(如 origin-when-cross-origin),或在局部使用 referrerpolicy 精细控制。
结论
- DouPHP 通过集中式配置与中间件下发 Referrer-Policy,默认采用严格平衡的 strict-origin-when-cross-origin。
- 可通过配置快速调整全站策略,并通过页面标签级 referrerpolicy 进行细粒度覆盖。
- 建议在大多数场景保持默认或更严格策略;仅在确有需要时放宽,并对敏感资源收紧。
附录:策略值与场景建议
策略值说明
- no-referrer:完全不发送 Referer 头,适用于高隐私场景,但可能影响统计与外链功能。
- no-referrer-when-downgrade:仅在 HTTPS→HTTP 降级时不发送 Referer,其余情况正常发送。
- origin:跨域请求只发送源(scheme+host+port),不发送路径;适合仅需来源的场景。
- origin-when-cross-origin:同源完整 URL,跨域仅发送源;兼顾统计与隐私,常用默认。
- same-origin:仅同源发送完整 Referer,跨域不发送;适合强隔离场景。
- strict-origin:跨域仅发送源,且 HTTPS→HTTP 降级时不发送;比 origin-when-cross-origin 更严格。
- strict-origin-when-cross-origin:同源完整 URL,跨域仅发送源,且 HTTPS→HTTP 降级时不发送;当前默认。
- unsafe-url:始终发送完整 URL,即使跨域和降级;存在较高隐私风险,不推荐。
业务场景推荐
- 表单提交(登录、注册、留言、订单提交等)
- 推荐:strict-origin-when-cross-origin 或 same-origin
- 理由:防止敏感路径被第三方站点获取,同时保留必要的来源信息用于站内分析。
- 第三方集成(广告、统计、支付回调)
- 推荐:origin-when-cross-origin 或 strict-origin
- 理由:多数第三方仅需来源即可工作;如需完整 URL,谨慎评估风险后再放宽。
- 用户分享与外链
- 推荐:origin-when-cross-origin
- 理由:平衡隐私与外链统计;必要时对个别外链使用 referrerpolicy 属性精细化控制。
- 管理后台
- 推荐:same-origin 或 strict-origin-when-cross-origin
- 理由:后台通常不应向外部泄露访问路径;必要时可结合 CSP 与权限控制。
与 CSP 中 referrer 指令的关系
- CSP 的 referrer 指令可限制页面发起的请求是否携带引用信息,与 Referrer-Policy 共同作用。
- 优先级与协作:
- Referrer-Policy 是响应头策略,作用于整个文档及其子资源。
- CSP 的 referrer 指令可对特定上下文做更细粒度的限制。
- 两者不一致时,浏览器会综合判断,通常以更严格者为准。
- 建议:
- 优先通过 Referrer-Policy 设定全局策略。
- 在需要更强控制的上下文中,配合 CSP 的 referrer 指令进行补充。
兼容性与测试方法
- 兼容性:
- 主流现代浏览器均支持 Referrer-Policy。
- 旧版浏览器会忽略未知策略值,建议使用标准值。
- 测试方法:
- 使用浏览器开发者工具查看响应头是否包含 Referrer-Policy 及值是否正确。
- 在不同场景下(同源、跨域、HTTPS→HTTP 降级)观察 Referer 头的实际行为。
- 对关键外链与第三方脚本进行回归测试,确保功能不受影响。
- 在模板中使用 referrerpolicy 属性进行局部覆盖,验证其优先级与效果。