如何安全地渲染html in react?

sil*_*513 22 html reactjs

我从文本区域获得了一些用户生成的html标记,我想将其渲染到屏幕的另一部分.标记在组件的props中保存为字符串.

出于显而易见的原因,我不想使用dangerouslysethtml.是否有一个解析器,如标记,但对于HTML,以便它删除脚本标签和其他无效的HTML.

Ori*_*ori 34

使用sanitize-html模块清理html,并使用dangerouslySetInnerHTML呈现已清理的字符串.

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

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)} />
);
Run Code Online (Sandbox Code Playgroud)

用法:

<SanitizeHTML html="<img src=x onerror=alert('img') />" />
Run Code Online (Sandbox Code Playgroud)

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

<SanitizedHTML
  allowedAttributes={{ 'a': ['href'] }}
  allowedTags={['a']}
  html={ `<a href="http://bing.com/">Bing</a>` }
/>
Run Code Online (Sandbox Code Playgroud)

  • 因为 sanitize-html 是对等依赖项,而不是包的实际部分。 (2认同)

jos*_*eir 19

基于接受的答案的示例:

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}}
    />
  );
};
Run Code Online (Sandbox Code Playgroud)

MyComponentdiv包含链接的渲染器没有onClick="evil()":

<a href="my-slug" target="_blank">click</a>
Run Code Online (Sandbox Code Playgroud)


Kon*_*lin 9

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

以下是/sf/answers/2706466941/ 中的包装器与 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)} />
);
Run Code Online (Sandbox Code Playgroud)

用法:

<SanitizeHTML html="<img src=x onerror=alert('img') />" />
Run Code Online (Sandbox Code Playgroud)

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