这更像是一个"你能确认这是正确的吗"类型的问题,因为我想我在编写问题的过程中解决了它,但希望它会对其他人有所帮助,他们在实施 DOMPurify 时有点犹豫
。简短版本
在前端js文件中导入和使用这样的DOMPurify
是否安全/有效:
npm install dompurify --save
import DOMPurify from 'dompurify';
var clean = DOMPurify.sanitize('<img src=x onerror=alert(1)//>', {SAFE_FOR_JQUERY: true});
详细版本
目前我的主要前端js文件使用以下约定导入:
import ClipboardJS from 'clipboard';
// date-fns functions
import getYear from 'date-fns/get_year';
import getMonth from 'date-fns/get_month';
import getDaysInMonth from 'date-fns/get_days_in_month';
import startOfMonth from 'date-fns/start_of_month';
import getDay from 'date-fns/get_day';
import format from 'date-fns/format';
import Cookies from './js.cookie';
我尝试了以下方法:
npm install dompurify --save
import DOMPurify from 'dompurify';
console.log(DOMPurify.sanitize('<img src=x onerror=alert(1)//>', {SAFE_FOR_JQUERY: true}));
console.log(DOMPurify.sanitize('<svg><g/onload=alert(2)//<p>', {SAFE_FOR_JQUERY: true}));
console.log(DOMPurify.sanitize('<p>abc<iframe//src=jAva	script:alert(3)>def', {SAFE_FOR_JQUERY: true}));
console.log(DOMPurify.sanitize('<math><mi//xlink:href="data:x,<script>alert(4)</script>">', {SAFE_FOR_JQUERY: true}));
console.log(DOMPurify.sanitize('<TABLE><tr><td>HELLO</tr></TABL>', {SAFE_FOR_JQUERY: true}));
console.log(DOMPurify.sanitize('<UL><li><A HREF=//google.com>click</UL>', {SAFE_FOR_JQUERY: true}));
字符串示例来自此处:
https://github.com/cure53/DOMPurify#some-purification-samples-please
并使用这里提到的SAFE_FOR_JQUERY
标志:
https://github.com/cure53/DOMPurify#can-i-configure-it
一切都按预期记录,即:
<img src="x">
<svg><g></g></svg>
<p>abcdef</p>
<math><mi></mi></math>
<table><tbody><tr><td>HELLO</td></tr></tbody></table>
<ul><li><a href="//google.com">click</a></li></ul>
所以这很好。
问题
官方 DOMPurify 自述文件显示了以下导入和使用方法:
// method 01
<script type="text/javascript" src="dist/purify.min.js"></script>
var clean = DOMPurify.sanitize(dirty);
// method 02
require(['dompurify'], function(DOMPurify) {
var clean = DOMPurify.sanitize(dirty);
});
// method 03
npm install dompurify
const createDOMPurify = require('dompurify');
const { JSDOM } = require('jsdom');
const window = (new JSDOM('')).window;
const DOMPurify = createDOMPurify(window);
const clean = DOMPurify.sanitize(dirty);
// method 04
const createDOMPurify = require('dompurify');
const jsdom = require('jsdom').jsdom;
const window = jsdom('').defaultView;
const DOMPurify = createDOMPurify(window);
const clean = DOMPurify.sanitize(dirty);
即使我没有列出我实现它的方式,这仍然是一种安全/有效的方法:
npm install dompurify --save
import DOMPurify from 'dompurify';
PS,如果需要上下文...
实现方案为:
01)
用户以跨度开头:
<span class="editable" data-previous_value="here is previously saved value">here is previously saved value</span>
02)
单击跨度时,data-previous_value
的值将添加到替换span
的input
元素中。
03)
用户修改input
元素中的文本并单击保存。
04)
我使用 markdown-it将html
选项设置为false
和 markdown-it-attrs(添加 css 样式(和 markdown-it-span(定义spans
(将任何 markdown 渲染为 html(链接、图像、类、跨度等(。
05)
新值将添加到新的span
元素(使用markdown-it
呈现(和替换input
元素的data
属性(未呈现(。
06)
新的、未呈现的值通过Node/Express
保存在数据库中MongoDB
。
例如,以下输入:
![img](/img/my_thumb.jpg){.video_thumb} [Video](https://www.youtube.com/watch?v=dQw4w9WgXcQ)
转换为以下 HTML:
<span class="editable" data-previous_value="![img](/img/my_thumb.jpg){.video_thumb} [Video](https://www.youtube.com/watch?v=dQw4w9WgXcQ)">
<img src="/img/my_thumb.jpg" alt="img" class="video_thumb">
<a href="https://www.youtube.com/watch?v=dQw4w9WgXcQ">Video</a>
</span>
我正在考虑在输入进入markdown-it
之前(在步骤 04 之前(用DOMPurify
清理输入。
对于 React:
import DOMPurify from "dompurify";
<div dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(dirtyContent) }} />
对于 React for
const SanitizedComponent = (props) => {
const reactComponentHtml = ReactDOMServer.renderToStaticMarkup(
props.children
);
const htmlSanatized = DOMPurify.sanitize(reactComponentHtml);
return <div>{parser(htmlSanatized)}</div>;
};
https://stackblitz.com/edit/react-ts-scwhqf?file=App.tsx