问题
Refused to load the script 'https://api.map.baidu.com/api?v=3.0&ak=xxxx&callback=onBMapCallback' because it violates the following Content Security Policy directive: "script-src 'self' 'unsafe-inline' 'unsafe-eval'". Note that 'script-src-elem' was not explicitly set, so 'script-src' is used as a fallback.
这个错误说明你的网页设置了 Content Security Policy (CSP),并且该策略限制了从外部源(如百度地图的 API)加载脚本。具体来说,当前的 CSP 只允许来自 'self'
(即同源站点)的脚本执行,并且禁止从其他来源加载 JavaScript 脚本。
解决方案
有几种方式可以解决这个问题,具体取决于你对安全性和需求的考量:
1. 修改 Content Security Policy 允许百度地图的脚本来源
你可以修改你的 Content Security Policy 规则,允许来自百度地图的脚本。将 https://api.map.baidu.com
添加到 script-src
指令中。
1.1. 在 HTML 中修改 CSP 头(如果通过 meta 标签设置):
找到你 HTML 文件中的 <meta>
标签,修改为:
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline' 'unsafe-eval' https://api.map.baidu.com;">
1.2. 在服务器端修改 CSP 头(如果通过 HTTP 响应头设置):
在你的服务器配置中,更新 Content-Security-Policy
响应头,允许从 https://api.map.baidu.com
加载脚本。
例如,对于 Nginx 服务器,可以这样修改配置:
add_header Content-Security-Policy "script-src 'self' 'unsafe-inline' 'unsafe-eval' https://api.map.baidu.com";
2. 使用 nonce 或 hash 安全性机制
如果你想保持较高的安全性,不仅仅是允许外部脚本,还可以通过使用 nonce
或 hash
来允许特定的外部脚本加载。
2.1. 使用 nonce
为外部脚本添加唯一的 nonce 值。修改你的 HTML 文件如下:
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline' 'unsafe-eval' 'nonce-randomString' https://api.map.baidu.com;">
然后,在你的 <script>
标签中添加相同的 nonce 值:
<script src="https://api.map.baidu.com/api?v=3.0&ak=&callback=onBMapCallback" nonce="randomString"></script>
2.2. 使用 sha256
哈希值
你也可以使用具体的 JavaScript 文件内容的哈希值来验证脚本的合法性。不过这在使用外部 CDN 动态加载时可能不太适合。
3. 放宽 CSP
如果你暂时无法精细控制 CSP 策略,可以将 script-src
改为一个更宽松的配置,例如:
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline' 'unsafe-eval' *;">
注意:这种做法降低了 CSP 的安全性,不建议在生产环境中长期使用。
4. 本地托管百度地图 API
如果你的项目对安全性要求非常严格,不希望放宽 CSP,可以考虑将百度地图 API 本地托管,并从本地加载。这样可以避免从外部源加载脚本导致的 CSP 问题。
配置说明
在您的HTML头部中定义了两段Content Security Policy (CSP),这两段配置有一些区别,我们分别来看一下它们的作用:
第一段配置
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline' 'unsafe-eval' https://api.map.baidu.com;">
- script-src:定义了哪些来源的脚本是可以执行的。
'self'
:允许从同一个源(即当前页面所在的源)加载脚本。'unsafe-inline'
:允许内联脚本(直接在HTML标签中使用<script>
标签)。'unsafe-eval'
:允许使用eval()
函数和Function()
构造函数。https://api.map.baidu.com/
:允许从百度地图API所在的源加载脚本。
第二段配置
<meta http-equiv="Content-Security-Policy" content="default-src *; child-src * 'self' blob: http:; img-src * 'self' data: http:; script-src 'self' 'unsafe-inline' 'unsafe-eval' *; style-src 'self' 'unsafe-inline' *">
- default-src:默认的源策略,应用于所有类型的内容(除非被更具体的指令覆盖)。这里的
*
意味着允许从任意源加载所有类型的资源。 - child-src:用于子资源,如iframe或web workers等。这里的配置允许从任何源加载子资源,但特别指定了
blob:
和http:
协议。 - img-src:定义了图像资源可以从哪些源加载。允许从任何源加载图像,并且特别指定了
data:
URL 和http:
协议。 - script-src:与第一段配置相同,允许从任何源加载脚本,并且包括内联脚本和使用
eval
的情况。 - style-src:定义了样式表可以从哪些源加载。允许从任何源加载样式,并且包括内联样式。
总结:
- 如果你的网页对安全性要求较高,建议细化 CSP 策略,允许特定的外部脚本加载。
- 如果是临时调试或测试,可以放宽 CSP 规则,但请谨慎使用。
链接
https://stackoverflow.com/questions/31211359/refused-to-load-the-script-because-it-violates-the-following-content-security-po