【问题标题】:How to make style element in Shadow DOM work with strict CSP?如何使 Shadow DOM 中的样式元素与严格的 CSP 一起工作?
【发布时间】: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


    【解决方案1】:

    2017 年的建议是使用 &lt;link&gt; 元素

    以下是来自 Apple (rniwa)、Google (hayatoito) 和 Mozilla (annevk) 的主要开发人员的评论:

    一个 2017 年的问题...可能打开它或创建一个新问题。

    顺便说一句,(与随机数无关)
    connectedCallback 中附加 shadowRoot 会在移动 DOM 元素时导致错误,因为 shadowRoot 只能添加一次(不能删除)

    所有东西都可以链接在constructor

      constructor() {
        super() // sets and returns 'this'
           .attachShadow({ mode: 'open' })  // sets and returns this.shadowRoot
           .append(template.content.cloneNode(true)); // no need for appendChild
      }
    

    【讨论】:

    • 感谢您的回答!我刚开始使用 Web 组件,我正在尝试弄清楚如何在我的组织中使用它们。在我的实验中,我尝试使用链接元素,但 CSP 阻止了它,就像它使用内联样式一样。你觉得这听起来正常吗?如果是,我怎样才能让它工作,如果不是,我可能会错过什么?
    • 对不起,我试过 CSP 一次......然后因为它是 PITA 而放弃它
    • 我不确定我上次尝试做错了什么,但在模板中使用链接元素可以像宣传的那样工作。有点烦人,你必须为 CSS 保留一个单独的文件,但如果没有额外的提取就不能为 HTML 保留一个,所以有点不对称,但至少它可以工作
    猜你喜欢
    • 1970-01-01
    • 2021-08-28
    • 2014-05-13
    • 2019-04-25
    • 2017-09-08
    • 2013-08-21
    • 2013-07-06
    • 1970-01-01
    • 2021-07-06
    相关资源
    最近更新 更多