广告

HTML转义字符有哪些?前端防XSS的5种安全编码方案与实战要点

一、HTML转义字符的基础与意义

HTML转义字符的定义与目的

HTML转义字符是将文本中的特殊字符转换为实体的表示方式,旨在避免将其解释为标签或脚本,从而实现安全的文本输出。

避免XSS攻击的场景中,正确使用转义字符可以确保用户输入安全地呈现为页面文本,而不被浏览器解析为可执行的代码。常见的转义实体包括 <>&"、以及 '(单引号)。

为了直观理解,直接输出的文本与转义后的文本在渲染结果上会有本质差异:前者可能触发标签解析和脚本执行,后者则以普通文本形式显示。

常见的转义字符及其含义

下列实体是前端开发中最常用的HTML转义集合:<(小于号)>(大于号)&(与号)"(引号)'(单引号)

HTML转义字符有哪些?前端防XSS的5种安全编码方案与实战要点

不同上下文中的转义需求可能不同,例如文本中直接输出与在属性中的区别。了解这些基本实体是实现鲁棒前端XSS防护的基础。

常用转义字符及实体:
<  =>  &lt;
>  =>  &gt;
&  =>  &amp;
"    =>  &quot;
'    =>  '

二、前端防XSS的5种安全编码方案与实战要点

方案1:HTML文本内容的转义(文本渲染上下文)

在需要将用户输入作为纯文本渲染到页面的场景,优先使用文本节点或文本属性,避免直接将输入拼接到 innerHTML 中。

实战要点:尽量使用 textContent/innerText 进行文本渲染,或通过 DOM API 将文本节点插入,而不是将文本直接插入到 HTML 字符串中。

// 方案1示例:文本渲染转义
const userInput = '<script>alert(1)</script>';
const container = document.getElementById('output');
container.textContent = userInput; // 浏览器自动对特殊字符转义,防止执行

要点回顾文本渲染优先级最高,防止任何未转义的标签结构进入文档流。

方案2:HTML属性值的编码(属性上下文)

将动态数据写入属性值时,应该确保数据在属性上下文中被正确编码,避免中断属性引号或注入额外事件处理程序。

实战中,浏览器对属性赋值相对安全,但直接拼接字符串再通过 innerHTML 注入属于高风险行为,应避免。

// 方案2示例:通过属性设置避免注入
const name = '" onmouseover="alert(1)"';
const el = document.createElement('div');
el.setAttribute('data-user', name); // 浏览器会对属性值进行合适编码
document.body.appendChild(el);

要点提示:尽量避免在属性值中拼接未转义的用户输入,必要时使用 API 提供的属性 setter,或先对值进行严格的转义再赋值。

方案3:JavaScript上下文的编码(脚本上下文)

当用户输入需要用于构造 JavaScript 字符串或脚本片段时,应该进行上下文敏感编码,防止结束当前字符串并执行注入的代码。

实战要点包括使用安全的字符串序列化方法与编码函数,例如使用 JSON.stringify 对输入进行可控编码,或使用严格的字符串替换策略。

// 方案3示例:在 JS 字符串中安全地嵌入用户输入
const userInput = '"; alert(1); //';
const safe = JSON.stringify(userInput); // 安全地表示为一个字符串字面量
const script = `var userInput = ${safe}; console.log(userInput);`;

要点总结避免在 JS 代码中拼接原始输入,应使用序列化或专用编码以免打断字符串边界。

方案4:CSS上下文的编码(样式属性与样式注入)

将数据注入到 CSS 上下文(如 style 属性或 style 代码块)时,应采用浏览器对 CSS 的编码机制,并在可能时使用 CSS.escape 等工具。

实战要点包含:在动态生成 CSS 值时,优先使用不依赖字符串拼接的方式;需要拼接时,使用 CSS.escape() 对用户输入进行转义。

// 方案4示例:CSS.escape 进行编码
const url = 'javascript:alert(1)';
const safe = CSS.escape(url);
element.style.backgroundImage = `url(${safe})`; // 安全应用

要点提示只信任经过 CSSescape 的结果,并避免直接将未转义的输入放入 style 属性中。

方案5:URL上下文的编码(查询字符串与路径)

将数据放入 URL(包括查询字符串、路径参数等)时应进行 URL 编码,避免注入恶意脚本或改写页面行为。

实战要点:使用 encodeURIComponentencodeURI 等原生方法对变量进行编码,避免在服务器端与客户端之间传递被篡改的 URL。

// 方案5示例:URL 编码
const userInput = '测试 & 脚本