关于前端:Sanitizer给你的DOM消消毒

3次阅读

共计 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)'>";

如果间接将其作为某个元素的 innerHTMLimgonerror回调执行 JS 代码的能力会带来 XSS 危险。

一种常见解决方案是:本义字符串。

什么是 escape

浏览器会将一些保留字符解析为 HTML 代码,比方:

  • <被解析为标签的结尾
  • >被解析为标签的结尾
  • ''被解析为属性值的结尾和结尾

为了将这些保留字符显示为文本(不被解析为 HTML 代码),能够将其替换为对应的 entityHTML 实体):

  • <的实体为&lt;
  • >的实体为&gt;
  • ''的实体为&quot;

这种将 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 呢?

欢送退出人类高质量前端框架钻研群,带飞

正文完
 0