如何配置内容安全策略允许谷歌API外部JS并移除unsafe-inline
'unsafe-inline'后谷歌地图脚本无法运行的问题 我明白你的困扰——移除'unsafe-inline'是正确的安全选择,但谷歌地图 Places API 的脚本加载后会动态生成内联代码块,这才是 CSP 阻止脚本运行的核心原因,光添加域名规则是不够覆盖这些内联内容的。下面给你几个靠谱的解决方案:
方案1:使用 Nonce(推荐,最安全灵活)
Nonce 是一个随机生成的一次性令牌,每次请求都不一样,能精准允许合法的内联脚本:
服务器端生成随机 Nonce:
以 Node.js 为例,你可以用 crypto 模块生成一个唯一值:const crypto = require('crypto'); const nonce = crypto.randomBytes(16).toString('base64');其他后端语言也有类似的随机字符串生成方法,确保每个请求的 nonce 唯一即可。
更新 CSP 的
script-src规则:
将生成的 nonce 加入规则,替换掉'unsafe-inline':script-src 'self' https://maps.googleapis.com https://maps.gstatic.com 'nonce-${YOUR_GENERATED_NONCE}';在谷歌地图脚本标签中添加 nonce 属性:
把服务器生成的 nonce 值嵌入到加载地图的<script>标签里:<script nonce="${YOUR_GENERATED_NONCE}" src="https://maps.googleapis.com/maps/api/js?key=${GOOGLE_API_KEY}&libraries=places&language=he"></script>谷歌地图的脚本会自动利用这个 nonce 标记它生成的内联代码,CSP 就会允许这些内联脚本执行了。
方案2:使用哈希(适合静态部署场景)
如果你的环境没法动态生成 nonce,可以通过哈希值允许特定的内联脚本:
临时恢复
'unsafe-inline'并获取哈希:
先把'unsafe-inline'加回 CSP,打开浏览器开发者工具的控制台,找到 CSP 阻止内联脚本的报错信息——里面会直接给出该内联脚本的 SHA-256/SHA-384/SHA-512 哈希值(格式类似'sha256-abcdef123456...')。将哈希加入 CSP 规则:
移除'unsafe-inline',把获取到的哈希值添加到script-src中:script-src 'self' https://maps.googleapis.com https://maps.gstatic.com 'sha256-YOUR_CALCULATED_HASH';⚠️ 注意:如果谷歌更新了他们的内联脚本内容,哈希值会失效,你需要重新计算更新,所以这个方案灵活性不如 nonce。
方案3:确认域名规则的完整性
虽然这不能解决内联脚本的问题,但确保你覆盖了所有谷歌地图相关的脚本源也很重要:
- 必须包含
https://maps.googleapis.com(主脚本源) - 必须包含
https://maps.gstatic.com(地图资源和辅助脚本) - 可以通过浏览器开发者工具的网络面板,查看所有加载的脚本域名,确保没有遗漏的子域名
最后再强调下:'unsafe-inline'确实会大幅增加XSS攻击的风险,用 nonce 或哈希是更安全的替代方案,优先推荐 nonce 方案。
内容的提问来源于stack exchange,提问作者Roy Hadad

