CSP识别的hash值需对内联脚本内容(不含<script>标签)做UTF-8编码后计算SHA-256,再base64编码;例如alert(1)生成sha256-qznLcsROx4GAYnkPvH3tkvhUL6Vf9o1IvEOw1mTHlJk=,填入script-src 'sha256-...'即可生效。
CSP的script-src支持'sha256-xxx'这类哈希白名单,但必须基于脚本内容(不含标签)做SHA-256计算,且编码为base64(无换行、无空格)。常见错误是直接对<script>alert(1)</script>整个字符串哈希——这会导致不匹配。
正确做法:只取alert(1)这部分内容(去除首尾<script>和</script>),UTF-8编码后计算SHA-256,再base64编码。例如:
echo -n "alert(1)" | shasum -a 256 | xxd -r -p | base64
输出类似sha256-qznLcsROx4GAYnkPvH3tkvhUL6Vf9o1IvEOw1mTHlJk=,这个值才能放进script-src 'sha256-qznLcsROx4GAYnkPvH3tkvhUL6Vf9o1IvEOw1mTHlJk='生效。
只要脚本内容在HTML渲染前就完全确定(即服务端静态生成、非客户端JS拼接),就可以生成哈希。但如果含服务端变量(如alert(<%= user.name %>)),哈希必须按最终渲染出的实际JS字符串计算——不同用户、不同上下文产生的哈希可能不同,不能复用。
立即学习“前端免费学习笔记(深入)”;
容易踩的坑:
${name})未被服务端解析,而是留到浏览器执行,此时哈希失效——CSP校验的是原始HTML里的文本,不是运行时结果document.write或eval动态注入的脚本,无法用hash白名单,CSP根本不检查那段内容每个<script>块需独立计算哈希,CSP策略中用空格分隔多个hash值。例如:
Content-Security-Policy: script-src 'sha256-A1B2...' 'sha256-C3D4...' 'self'
但要注意:
Refused to execute inline script,不提示具体哪条没匹配'unsafe-inline'调试,但上线前必须移除——它会使所有hash规则失效最常忽略的是HTML解析细节:
<script>console.log(1)</script>和<script type="text/javascript">console.log(1)</script>算作不同内容,后者多出type="text/javascript"字符串,哈希必然不同rn)而Linux工具默认用n,也会导致哈希错位<meta http-equiv="Content-Security-Policy">声明,但该标签位置在<script>之后,部分浏览器会忽略)真要靠hash白名单,就得把内联脚本当作“编译产物”来对待:内容锁定、生成自动化、上线前验证。稍有松动,就只剩报错和空白控制台。