共计 1885 个字符,预计需要花费 5 分钟才能阅读完成。
大家好,我卡颂。
业务中常常遇到须要解决 有危险的 DOM的场景,比方:
- 各种工具的文本粘贴性能
- 须要渲染服务端返回
HTML
的场景
为了阻止潜在的 XSS
攻打,有两个抉择:
escape
(本义)sanitize
(消毒)
本文会介绍这两者的区别以及为 DOM
消毒的API
—— Sanitizer
。
本文内容来自 Safe DOM manipulation with the Sanitizer API
本义与消毒
假如,咱们想将这样一段 HTML
字符串插入DOM
:
const str = "<img src='' onerror='alert(0)'>";
如果间接将其作为某个元素的 innerHTML
,img
的onerror
回调执行 JS
代码的能力会带来 XSS
危险。
一种常见解决方案是:本义字符串。
什么是 escape
浏览器会将一些保留字符解析为 HTML
代码,比方:
<
被解析为标签的结尾>
被解析为标签的结尾''
被解析为属性值的结尾和结尾
为了将这些保留字符显示为文本(不被解析为 HTML
代码),能够将其替换为对应的 entity
(HTML
实体):
<
的实体为<
>
的实体为>
''
的实体为"
这种将
HTML
字符替换为entity
的形式被称为escape
(本义)
什么是 sanitize
对于下面的 HTML
字符串:
const str = "<img src='' onerror='alert(0)'>";
除了本义 ''
来躲避 XSS
危险,还有一种更直观的思路:间接过滤掉 onerror
属性。
这种间接移除
HTML
字符串中无害的代码(比方<script>
)的形式被称为sanitize
(消毒)
须要用到一个API
——Sanitizer。
首先咱们通过 Sanitizer
结构实例:
const sanitizer = new Sanitizer();
调用实例的 sanitizeFor
办法,传入容器元素类型以及要消毒的 HTML
字符串:
sanitizer.sanitizeFor("div", str);
会失去一个 HTMLDivElement
(即咱们传入的容器元素类型),其外部蕴含一个没有onerror
属性的img
:
默认状况下 Sanitizer
会移除所有可能导致 JS
执行的代码。
丰盛的配置
Sanitizer
不仅开箱即用,还提供丰盛的白名单、黑名单配置:
const config = {allowElements: [],
blockElements: [],
dropElements: [],
allowAttributes: {},
dropAttributes: {},
allowCustomElements: true,
allowComments: true
};
new Sanitizer(config)
比方,allowElements
定义元素白名单,只有名单内的元素会被保留,与之对应的 blockElements
是元素黑名单:
const str = `hello <b><i>world</i></b>`
new Sanitizer().sanitizeFor("div", str)
// <div>hello <b><i>world</i></b></div>
new Sanitizer({allowElements: [ "b"]}).sanitizeFor("div", str)
// <div>hello <b>world</b></div>
new Sanitizer({blockElements: [ "b"]}).sanitizeFor("div", str)
// <div>hello <i>world</i></div>
new Sanitizer({allowElements: []}).sanitizeFor("div", str)
// <div>hello world</div>
allowAttributes
是属性白名单,与之对应的 dropAttributes
是属性黑名单,对于如下配置:
{allowAttributes: {"style": ["span"]},
dropAttributes: {"id": ["*"]}}
}
代表消毒后的HTML
:
- 只容许
span
元素领有style
属性 - 移除所有元素(
*
通配符代表所有元素)的id
属性
兼容性
这么香的 API
兼容性怎么样呢:
以后只有在 Chrome 93
之后,开启试验标识后可应用:
about://flags/#enable-experimental-web-platform-features
尽管原生 Sanitizer
离稳固还遥遥无期,但你能够应用 DOMPurify 库实现相似性能。
后记
日常你更偏向应用 escape
还是 sanitize
呢?
欢送退出人类高质量前端框架钻研群,带飞