首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用dangerouslySetInnerHTML执行脚本

用dangerouslySetInnerHTML执行脚本
EN

Stack Overflow用户
提问于 2020-10-05 00:46:07
回答 1查看 3.6K关注 0票数 1

我在几个地方读到,当我们使用React dangerouslySetInnerHTML插入html片段时,脚本不会被执行。

不过,我只是尝试插入以下内容:

代码语言:javascript
复制
<img src= "img.png" onload="alert('picture loaded')" alt="script test">  

警报被触发了。

这并不让我感到惊讶(这就是我最初做这个测试的原因),但我想更好地理解我们所说的“脚本不执行”的含义。

我的问题:

  • 除了上面的例子外,还有其他类型的脚本可以执行吗?
  • 是否有办法完全防止脚本执行,包括嵌入在html事件处理程序中的脚本,就像我的示例中那样?如果脚本标记定义了一个函数,那么该函数还会加载并在以后被调用吗?
  • ,我应该注意的其他行为?

f 211

在函数组件中使用dangerouslySetInnerHTML编辑:

代码语言:javascript
复制
const htmlString = '<img src="img.png" onload="alert('picture loaded')" alt="script test">'

在返回声明(JSX)中:

代码语言:javascript
复制
return <div dangerouslySetInnerHTML={{__html: htmlString}} />
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-10-05 00:52:57

“不会执行”的脚本是脚本标记,如<script>。参见这里的一个例子:

代码语言:javascript
复制
const html = `
<script>console.log('this does NOT run');<\/script>
<img src onerror="console.log('but this will')">
`;
const App = () => {
  return <div dangerouslySetInnerHTML={{__html: html}} />;
};
ReactDOM.render(<App />, document.querySelector('.react'));
代码语言:javascript
复制
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div class="react"></div>

内联处理程序,而不是<script>标记,可以运行,如果事件附加到火。(上面,具有<img>属性但没有有效路径的src标记引发错误,因此它的onerror内联处理程序运行)

没有其他类型的脚本将与dangerouslySetInnerHTML一起运行(除非内联处理程序本身以其他方式注入<script>,如document.createElement('script'))。

是否有一种方法可以完全防止脚本执行,包括嵌入在html事件处理程序中的脚本(如我的示例中所示)?

您需要删除on-属性。如果删除了所有on-属性,那么任何可能触发的事件都不会导致意外脚本的运行。您可以首先通过DOMParser发送输入:

代码语言:javascript
复制
const sanitize = (input) => {
  const doc = new DOMParser().parseFromString(input, 'text/html');
  for (const elm of doc.querySelectorAll('*')) {
    for (const attrib of elm.attributes) {
      if (attrib.name.startsWith('on')) {
        elm.removeAttribute(attrib.name);
      }
    }
  }
  return doc.body.innerHTML;
};

const html = `
<div>
  <script>console.log('this does NOT run');<\/script>
  <img src onerror="console.log('but this will')">
  more content
  <style type="text/css"> img {float: left; margin: 5px}</style> 
</div>
`;
const App = () => {
  return <div dangerouslySetInnerHTML={{__html: sanitize(html)}} />;
};
ReactDOM.render(<App />, document.querySelector('.react'));
代码语言:javascript
复制
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div class="react"></div>
<img src="https://www.gravatar.com/avatar/f117a950c689d3d6ec459885a908166e?s=32&d=identicon&r=PG">

如果一个脚本标记定义了一个函数,那么该函数是否仍然会被加载并在以后被调用?

不,因为<script>标记将根本没有运行,所以在它内部进行的任何操作都不会做任何事情;在其中定义的函数不会变得可见。要使这种情况发生,您必须以某种方式使新注入的deliberately reload标记运行起来。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64201229

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档