如何在反应中安全地呈现 html?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/38663751/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-29 13:39:32  来源:igfitidea点击:

How to safely render html in react?

htmlreactjs

提问by silverlight513

I've got some user generated html markup from a text area and I'd like to render it on another part of the screen. The markup is saved as a string in the props of the component.

我有一些用户从文本区域生成的 html 标记,我想在屏幕的另一部分呈现它。标记以字符串形式保存在组件的 props 中。

I don't want to use dangerouslysethtml for obvious reasons. Is there a parser such as markedbut for html so that it strips out script tags and other invalid html.

出于显而易见的原因,我不想使用危险的sethtml。是否有诸如标记的解析器,但用于 html,以便它去除脚本标记和其他无效的 html。

回答by Ori Drori

Sanitize the html using the sanitize-htmlmodule, and render the sanitized string using dangerouslySetInnerHTML.

消毒使用的HTML的sanitize-HTML模块,并呈现使用消毒串dangerouslySetInnerHTML

You can create a simple wrapper component:

您可以创建一个简单的包装器组件:

const defaultOptions = {
  allowedTags: [ 'b', 'i', 'em', 'strong', 'a' ],
  allowedAttributes: {
    'a': [ 'href' ]
  },
  allowedIframeHostnames: ['www.youtube.com']
};

const sanitize = (dirty, options) => ({
  __html: sanitizeHtml(
    dirty, 
    options: { ...defaultOptions, ...options }
  )
});

const SanitizeHTML = ({ html, options }) => (
  <div dangerouslySetInnerHTML={sanitize(html, options)} />
);

Usage:

用法:

<SanitizeHTML html="<img src=x onerror=alert('img') />" />


You can also use react-sanitized-html's SanitizedHTML component, which is a react wrapper around sanitize-html:

您还可以使用react-sanitized-html的 SanitizedHTML 组件,它是一个围绕sanitize-html以下内容的反应包装器:

<SanitizedHTML
  allowedAttributes={{ 'a': ['href'] }}
  allowedTags={['a']}
  html={ `<a href="http://bing.com/">Bing</a>` }
/>

回答by joshweir

An example based on the accepted answer:

基于已接受答案的示例:

import sanitizeHtml from 'sanitize-html';

const MyComponent = () => {
  dirty = '<a href="my-slug" target="_blank" onClick="evil()">click</a>';
  const clean = sanitizeHtml(dirty, {
    allowedTags: ['b', 'i', 'em', 'strong', 'a'],
    allowedAttributes: {
      a: ['href', 'target']
    }
  });
  return (
    <div 
      dangerouslySetInnerHTML={{__html: clean}}
    />
  );
};

MyComponentrenders divcontaining the link without onClick="evil()":

MyComponent渲染div包含不带链接的链接onClick="evil()"

<a href="my-slug" target="_blank">click</a>

回答by Konstantin Komelin

For XSS filtering, there is a good alternative to sanitize-htmlwritten by security people, called dompurify.

对于 XSS 过滤,有一个很好的替代安全人员编写的sanitize-html,称为dompurify

Here is how the wrapper from https://stackoverflow.com/a/38663813/1762849would look with DOMPurify:

以下是https://stackoverflow.com/a/38663813/1762849 中的包装器与 DOMPurify 的外观:

const defaultOptions = {
  ALLOWED_TAGS: [ 'b', 'i', 'em', 'strong', 'a' ], 
  ALLOWED_ATTR: ['href']
};

const sanitize = (dirty, options) => ({
  __html: DOMPurify.sanitize(
    dirty, 
    { ...defaultOptions, ...options }
  )
});

const SanitizeHTML = ({ html, options }) => (
  <div dangerouslySetInnerHTML={sanitize(html, options)} />
);

Usage:

用法:

<SanitizeHTML html="<img src=x onerror=alert('img') />" />


Also, if you you need to sanitize HTML on client and server, consider using the isomophic-dompurifymodule which unifies use of DOMPurify on frontend and backend.

此外,如果您需要清理客户端和服务器上的 HTML,请考虑使用isomophic-dompurify模块,该模块在前端和后端统一使用 DOMPurify。