如何在反应中安全地呈现html?
Posted
技术标签:
【中文标题】如何在反应中安全地呈现html?【英文标题】:How to safely render html in react? 【发布时间】:2016-12-04 11:05:38 【问题描述】:我从文本区域获得了一些用户生成的 html 标记,我想将它呈现在屏幕的另一部分。标记作为字符串保存在组件的 props 中。
出于明显的原因,我不想使用危险的sethtml。是否有诸如 marked 之类的解析器,但用于 html,以便它去除脚本标签和其他无效的 html。
【问题讨论】:
【参考方案1】:对于 XSS 过滤,安全人员编写的 sanitize-html 有一个很好的替代方案,称为 dompurify。
以下是来自https://***.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) />
);
用法:
<SanitizeHTML html="<img src=x onerror=alert('img') />" />
另外,如果您需要清理客户端和服务器上的 HTML,请考虑使用 isomophic-dompurify 模块,该模块在前端和后端统一使用 DOMPurify。
【讨论】:
这似乎是一个更好的选择,因为它提供了所需要的 @15kB bundlephobia.com/result?p=dompurify@2.1.1【参考方案2】:使用 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) />
);
用法:
<SanitizeHTML html="<img src=x onerror=alert('img') />" />
您还可以使用react-sanitized-html 的 SanitizedHTML 组件,它是sanitize-html
周围的反应包装器:
<SanitizedHTML
allowedAttributes= 'a': ['href']
allowedTags=['a']
html= `<a href="http://bing.com/">Bing</a>`
/>
【讨论】:
我不明白react-sanitized-html@2.0.0
是sanitize-html
的一个包装器,而sanitize-html@1.20.0
是157.2kB 时只有2kb:/!
好的,因为需要分别安装两个包... react-sanitized-html 和 sanitize-html :/
因为 sanitize-html 是对等依赖项,而不是包的实际部分。
您好@ori,我正在按照您的指示进行操作,但我的编译器出现错误[11:40:00] Starting 'browserify_typescript'... [11:40:04] 'browserify_typescript' errored after 4.29 s [11:40:04] Error in plugin 'gulp-browserify' module "./tagtypes" not found from "/d/myProject/web/node_modules/sanitize-html/dist/sanitize-html.js"
它说./tagtypes not found
这是与构建相关的问题。您应该提出一个新问题。【参考方案3】:
基于已接受答案的示例:
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
/>
);
;
MyComponent
呈现 div
包含不带 onClick="evil()"
的链接:
<a href="my-slug" target="_blank">click</a>
【讨论】:
以上是关于如何在反应中安全地呈现html?的主要内容,如果未能解决你的问题,请参考以下文章
如何使 HTML 面向列和基于 div 的表格的高度在反应中相同