简介
本文件面向DouPHP站点,提供Permissions-Policy安全响应头的落地方案。内容涵盖:
- 在DouPHP中如何集中配置并下发Permissions-Policy头
- 常用权限(camera、microphone、geolocation、payment、usb等)的启用/禁用策略
- 最小权限原则的实践建议
- 与Feature-Policy的关系及迁移注意事项
- 权限检测与功能降级处理思路
- 不同业务场景下的推荐配置模板
项目结构
DouPHP通过统一的中间件机制在HTTP边界下发安全响应头,其中包含X-Content-Type-Options、X-Frame-Options、Referrer-Policy以及Permissions-Policy。具体实现由基类中间件读取配置并写入响应头,前台、后台、API三端各自继承该基类以复用相同行为。
graph TB
A["请求进入"] --> B["前端中间件<br/>front/middleware/SecurityHeadersMiddleware"]
A --> C["后台中间件<br/>admin/middleware/SecurityHeadersMiddleware"]
A --> D["API中间件<br/>api/middleware/SecurityHeadersMiddleware"]
B --> E["基类中间件<br/>AbstractSecurityHeadersMiddleware"]
C --> E
D --> E
E --> F["读取配置<br/>config/security.php"]
E --> G["设置响应头<br/>包括 Permissions-Policy"]
G --> H["继续处理请求"]
核心组件
- 安全响应头中间件基类:负责从配置中读取headers并写入响应头,包含Permissions-Policy。
- 三端中间件薄壳:前台、后台、API分别继承基类,统一行为。
- 安全配置:集中定义各安全头值,包括permissions_policy字段。
架构总览
下图展示了请求到达后,中间件如何读取配置并下发Permissions-Policy头,随后继续路由处理。
sequenceDiagram
participant Client as "客户端"
participant MW as "SecurityHeadersMiddleware(三端)"
participant BaseMW as "AbstractSecurityHeadersMiddleware"
participant CFG as "Config(security.headers)"
participant Next as "后续处理器"
Client->>MW : HTTP请求
MW->>BaseMW : handle(next)
BaseMW->>CFG : 读取 security.headers
BaseMW-->>BaseMW : 校验 headers_sent()
BaseMW->>Client : 设置 X-Content-Type-Options / X-Frame-Options / Referrer-Policy / Permissions-Policy
BaseMW->>Next : 继续处理请求
Next-->>Client : 业务响应
详细组件分析
安全响应头中间件基类
- 职责:在管道最前置读取配置并下发一组基线安全头;仅在HTTPS且开启时下发HSTS;仅对已匹配路由生效。
- 关键点:当配置项存在且未发送过响应头时,会写入对应响应头,包括Permissions-Policy。
flowchart TD
Start(["进入 handle"]) --> ReadCfg["读取 security.headers"]
ReadCfg --> CheckSent{"是否已发送响应头?"}
CheckSent -- "是" --> Skip["跳过设置"]
CheckSent -- "否" --> SetHeaders["设置安全头<br/>含 Permissions-Policy"]
SetHeaders --> Next["调用 next() 继续处理"]
Skip --> Next
三端中间件薄壳
- 前台、后台、API均继承基类,不改变默认行为,确保三端一致地下发安全头。
安全配置(security.headers)
- 位置:config/security.php中的security.headers数组。
- 关键字段:
- permissions_policy:字符串,空串表示关闭该头;非空则作为Permissions-Policy值下发。
- 其他相关头:frame_options、content_type_options、referrer_policy、hsts。
- 当前默认值示例:已包含对geolocation、microphone、camera的限制。
依赖关系分析
- 中间件依赖配置:AbstractSecurityHeadersMiddleware通过配置中心读取security.headers,再写入响应头。
- 三端复用:前台、后台、API中间件均依赖同一基类,保证一致性。
- 运行时约束:仅在headers未发送时写入,避免重复或错误覆盖。
graph LR
CFG["config/security.php"] --> BASE["AbstractSecurityHeadersMiddleware"]
BASE --> FRONT["front SecurityHeadersMiddleware"]
BASE --> ADMIN["admin SecurityHeadersMiddleware"]
BASE --> API["api SecurityHeadersMiddleware"]
性能与安全考量
- 性能:中间件仅在命中路由时执行,且仅在headers未发送时写入,开销极低。
- 安全:
- 通过集中配置统一管理,减少遗漏风险。
- 默认限制敏感权限(如geolocation、microphone、camera),降低滥用面。
- HSTS仅在HTTPS且显式开启时下发,避免误配导致不可逆问题。
故障排查指南
- 现象:浏览器控制台提示某权限被拒绝(如“Geolocation denied”)。
- 检查:确认config/security.php中permissions_policy是否限制了相应权限。
- 调整:如需启用,修改对应权限值为允许源(例如自身域名或空列表表示允许所有,需谨慎评估)。
- 现象:未看到Permissions-Policy响应头。
- 检查:确认中间件已挂载到路由管道,且headers尚未发送。
- 定位:查看AbstractSecurityHeadersMiddleware是否在handle阶段执行。
- 现象:HSTS未生效。
- 检查:是否为HTTPS环境且hsts.enabled为true。
结论
DouPHP通过集中化的安全响应头中间件和配置,提供了简单、一致的Permissions-Policy下发能力。建议遵循最小权限原则,按需启用敏感权限,并结合业务场景进行差异化配置。对于需要兼容旧版浏览器的场景,可考虑同时保留Feature-Policy作为过渡。
附录:场景化配置模板与迁移指南
常见权限说明与影响
- camera:控制摄像头访问。限制后可防止网页任意调用摄像头,提升隐私保护。
- microphone:控制麦克风访问。限制后可避免未经授权的音频采集。
- geolocation:控制地理位置访问。限制后可阻止网页获取用户位置信息。
- payment:控制支付API。限制后可避免第三方脚本触发支付流程。
- usb:控制USB设备访问。限制后可防止恶意设备枚举与通信。
最小权限原则实践
- 默认禁止敏感权限,仅在必要时放开给可信源。
- 使用精确源(如自身域名)而非通配符,避免过度授权。
- 定期审计页面与第三方脚本,及时收紧权限。
与Feature-Policy的关系与迁移
- Feature-Policy是早期草案规范,Permissions-Policy是其演进版本,语义更清晰、支持更广。
- 迁移建议:
- 优先使用Permissions-Policy;若需兼容旧浏览器,可同时下发两者。
- 逐步移除Feature-Policy,统一维护至Permissions-Policy。
- 注意键名差异与取值变化,逐项核对。
权限检测与功能降级
- 前端检测:在调用敏感API前,先检测权限状态,若被拒绝则提供降级方案(如引导用户手动授权或切换功能)。
- 用户体验:明确告知用户权限被拒绝的原因与影响,并提供替代路径。
- 后端配合:对关键操作增加服务端校验,避免仅依赖前端权限判断。
不同业务场景推荐配置模板
- 纯展示型电商站点(无音视频、无定位)
- 建议:保持默认限制(geolocation=(), microphone=(), camera=()),不启用payment、usb。
- 直播/视频站点(需要摄像头、麦克风)
- 建议:在必要页面启用camera、microphone,并限定可信源;其余页面保持限制。
- 地图/本地服务站点(需要定位)
- 建议:仅在地图相关页面启用geolocation,并限定可信源;其他页面保持限制。
- 在线支付集成(需要payment)
- 建议:仅在支付流程页面启用payment,严格限定可信源;其他页面保持限制。
- 外设交互站点(需要usb)
- 建议:仅在必要页面启用usb,严格限定可信源;其他页面保持限制。