Apache单条与多条Content Security Policy Header指令是否等价?
我正在配置Content Security Policy(CSP),对Apache的多Header指令有疑问。已知可以设置多个CSP Header,但最终生效的是最严格的规则,比如:
Content-Security-Policy: img-src 'self'; Content-Security-Policy: img-src 'self' img.example.com;
实际生效的是img-src 'self',因为它更严格。
为了让Apache配置文件更易读,我想把每个CSP分类拆分开。现在想确认:下面这条单行Apache Header指令:
Header Set Content-Security-Policy "frame-src 'self' https://*.example.com https://*.youtube.com ; style-src 'self' https://CssAssets.example.com ; font-src 'self' *.googlefonts.com ; script-src-elem 'self' https://www.googletagmanager.com 'sha256-/5FvV9Vy9L+Q8i33gdJ9sHKsx4DwjcuiL0tBoqqJ/EE=' ; script-src 'unsafe-inline' ; default-src 'self' example.gov ;"
是否和以下多条指令等价?
Header Set Content-Security-Policy "frame-src 'self' https://*.example.com https://*.youtube.com ; " Header Add Content-Security-Policy "style-src 'self' https://CssAssets.example.com ; " Header Add Content-Security-Policy "font-src 'self' *.googlefonts.com ; " Header Add Content-Security-Policy "script-src-elem 'self' https://www.googletagmanager.com 'sha256-/5FvV9Vy9L+Q8i33gdJ9sHKsx4DwjcuiL0tBoqqJ/EE=' ; " Header Add Content-Security-Policy "script-src 'unsafe-inline' ; " Header Add Content-Security-Policy "default-src 'self' example.gov ; "
不等价,两者的行为有本质区别
单条
Header Set指令的效果
这条指令会生成单个CSP Header,所有规则合并在同一个策略中。浏览器会将所有规则视为一个整体,比如script-src和script-src-elem会按CSP的优先级规则共同生效(script-src-elem会覆盖script-src中对应类型的规则),整个策略的限制是各规则的组合效果。多条
Set + Add指令的效果Header Set会先设置第一个CSP Header,后续的Header Add会添加多个独立的CSP Header。根据CSP的规则,浏览器会对每个独立的CSP Header分别评估,然后取所有策略中最严格的限制生效。
举个核心差异的例子:
- 第一个Header的规则是
frame-src 'self' https://*.example.com https://*.youtube.com - 最后一个Header的规则是
default-src 'self' example.gov
此时浏览器会同时应用这两个独立的策略:对于frame资源,第一个策略允许self和指定域名,第二个策略的default-src会限制frame资源只能从self和example.gov加载,最终生效的是两者的交集——只有self符合要求,其他frame域名都会被拦截。
而单条指令中,frame-src明确指定了允许的域名,会覆盖default-src对frame的限制,所以所有指定的frame域名都是被允许的。
另外,script-src和script-src-elem在多Header场景下,也会被分别评估取最严格规则,和单条指令中两者的优先级逻辑完全不同。
如果想拆分配置又保持和单条指令等价,不要用多个Header Add添加独立的CSP Header,而是应该用单条Header Set指令,将规则拆分成多行(Apache支持配置换行),比如:
Header Set Content-Security-Policy " \ frame-src 'self' https://*.example.com https://*.youtube.com; \ style-src 'self' https://CssAssets.example.com; \ font-src 'self' *.googlefonts.com; \ script-src-elem 'self' https://www.googletagmanager.com 'sha256-/5FvV9Vy9L+Q8i33gdJ9sHKsx4DwjcuiL0tBoqqJ/EE='; \ script-src 'unsafe-inline'; \ default-src 'self' example.gov; \ "
这种方式既保持了配置的可读性,又和原单条指令的行为完全一致。
内容的提问来源于stack exchange,提问作者user208145

