CSP 的 hash 值怎么算才对?为什么我加了还是报错?
我在给一个内联脚本加 CSP 的 hash 策略,但浏览器一直报违反策略。我用的是 sha256,命令是 echo -n "alert('hello')" | openssl dgst -sha256 -binary | base64,结果加到 header 里还是不行。
我的 HTML 是这样的:
<script>
alert('hello')
</script>
而 CSP 头设置的是:
Content-Security-Policy: script-src 'sha256-xxxxx...';
到底哪里出错了?是不是换行符或者空格的问题?
问题出在换行符上。你的 HTML 脚本是这样的:
注意,
和alert之间有个换行,alert 后面还有个换行。你计算 hash 用的内容是alert('hello')(没换行),但浏览器看到的实际内容是带换行的。正确的计算方式:
或者用这种方式更直观:
还有个坑是 openssl 版本问题,有些版本输出会带
(stdin)=前缀,加上-r参数或者直接用shasum更稳:还有个事儿提醒一下,CSP 的 hash 值格式是
'sha256-xxxxx',前面那个单引号别漏了:你先用上面的命令重新算一下,应该就过了。
CSP 的 hash 计算有个坑,它要 hash 的是 script 标签里面的所有东西,包括换行符、空格、缩进,一个字符都不能差。
你的 HTML 是这样的:
那 script 标签里面的内容其实是「换行符 + alert('hello') + 换行符」,不是单纯的
alert('hello')。正确的计算方式应该是这样的:
或者更省事的做法,直接把 script 标签里的内容存成文件,包括换行符,然后用文件来算:
算出来的 hash 前面加上
sha256-就能用了。顺便说一句,如果你是在 WordPress 里面折腾这个,可以用
send_headers钩子来加 CSP 头,省得改服务器配置:还有个调试小技巧,Chrome 开发者工具控制台里报错的时候,会直接告诉你它期望的 hash 值是什么,拿那个直接用就行,省得自己算半天还算错。