我正在站点上实现内容安全策略 (CSP)。以下是我正在测试的 CSP 政策。
Content-Security-Policy: script-src 'self' 'nonce-random' 'strict-dynamic';
本站使用第三方js脚本库。脚本库在页面上注入(inject)动态内容。动态内容具有内联事件处理程序。下面是一个简单的 HTML 页面,其中包含模拟网站和第三方库行为的脚本。
<!DOCTYPE html>
<html>
<head>
<title>CSP Test Page</title>
<script nonce="random">
document.addEventListener('DOMContentLoaded', function (event) {
var el = document.createElement('button');
el.innerHTML = 'Click Me';
el.setAttribute('onclick', "doSomething()");
document.body.appendChild(el);
});
function doSomething() {
alert('I did something.');
}
</script>
</head>
<body>
</body>
</html>
动态添加按钮上的内联事件处理程序在 Chrome 控制台中触发以下错误消息:
Refused to execute inline event handler because it violates the following Content Security Policy directive: "script-src 'self' 'nonce-random' 'strict-dynamic'". Either the 'unsafe-inline' keyword, a hash ('sha256-...'), or a nonce ('nonce-...') is required to enable inline execution.
对于如何从 CSP 的角度解决这个问题有什么建议吗?我无法更改使用内联事件处理程序添加动态生成的内容的第三方库的代码。
最佳答案
CSP 会阻止所有内联事件处理程序,包括第三方库添加的代码,因此不幸的是,如果不重构与 CSP 不兼容的依赖项,没有简单的方法可以解决此问题。
从长远来看,CSP3 可能会通过 'unsafe-hashed-attributes'
提供将事件处理程序中的受信任脚本列入白名单的能力。功能,但尚未在任何稳定的浏览器中发布。
与此同时,一种可能的解决方法是在调用外部库后使用内联事件处理程序手动删除该属性。也就是说,您可以执行以下操作:
var el = document.createElement('button');
library.doStuff(el);
// Now that the library has run we will change the DOM to be compatible with CSP.
el.onclick = function() { doSomething() };
el.removeAttribute('onclick');
请注意,对于 CSP,直接将函数分配给 onclick
属性是可以的,而不是在 HTML 元素上设置 onclick 属性,后者被阻止通过 CSP,因为它将字符串转换为代码。这将起作用并避免违反 CSP,但只有在库中有少量内联事件处理程序实例时才有意义;否则这会变得非常乏味。
作为旁注,您的 CSP 可能会受益于不支持 'strict-dynamic'
的旧浏览器的回退,类似于 this example .
关于html - 带有动态按钮的内容安全策略,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47021481/