【发布时间】:2021-09-04 08:39:15
【问题描述】:
近年来,Web Components 标准已成为 Web 的标准低级 GUI API。它的主要特性之一是 Shadow DOM,它封装了 DOM,从而大大简化了 CSS 选择器。
一个基本的例子可能是,
const template = document.createElement('template');
template.innerHTML = /*html*/`
<style>
p {
color: red;
}
</style>
<p>Hello, world!</p>
`;
class HelloWorld extends HTMLElement {
constructor() {
super();
}
connectedCallback() {
this.attachShadow({ mode: 'open' });
this.shadowRoot.appendChild(template.content.cloneNode(true));
}
}
customElements.define('hello-world', HelloWorld);
在我的 HTML 中,我会这样称呼我的组件,
<!DOCTYPE html>
<html>
<head>
<script type="module" src="hello-world.js" defer></script>
</head>
<body>
<hello-world></hello-world>
</body>
</html>
这种方法正在被巩固为行业基线,其中包括 Lit、React、Angular、Vue 等框架。现在假设我要应用严格的 CSP。
为此,我从以下政策开始,
Content-Security-Policy "default-src 'self';"
但它不起作用,因为 web 组件定义中的样式元素是内联的。我知道的唯一解决方案是添加随机数、哈希或不安全内联。我不会考虑 unsafe-inline,因为它降低了安全性,从而否定了问题的重点,即保持严格的 CSP。让我们考虑其他两种选择。
这是我开始猜测的地方,如果我错了,请纠正我。除了最简单的情况外,制作散列或随机数是不可能的。只有完全静态的内容才能使用哈希。一旦内容变成动态的,hash 就会出错,CSP 就会阻塞内联样式。这与为嵌入在定义 Web 组件的 js 文件中的 HTML 创建哈希值无关。随机数提出了一个不同的、同样困难的问题。假设我生成了一个随机数并将其包含在我的 CSP 标头中。如何将其注入到js文件中?
除了添加到 CSP 规范以允许允许的脚本添加内联样式之外,我无法想象一个合理的解决方案。
如何以任何方式做到这一点?
【问题讨论】:
标签: html css content-security-policy shadow-dom native-web-component