es6模板字符串不自动转义html,易致xss;安全做法:纯文本用textcontent,需html时用htmlescape或dompurify,服务端与前端须双重转义。

ES6 模板字符串本身不处理HTML转义,也不防范注入攻击。它只是语法糖,${} 插值是纯字符串替换,不会自动转义 、&、"、' 等危险字符。真正安全的关键,在于你把模板字符串拼出来的内容用在什么位置、怎么插入 DOM。
别让模板字符串 + innerHTML 成为 XSS 渠道
这是最常见也最危险的组合:
- 用户输入
<img src="x" onerror="alert(1)"> - 你写:
const html = <div>${userInput}</div>; el.innerHTML = html; - 浏览器立刻执行脚本——XSS 已发生
模板字符串在这里没做任何防护,它忠实地把原始输入嵌入了 HTML 字符串中。
安全做法:按输出位置选择处理方式
显示纯文本(95% 场景)→ 用 textContent
- 完全绕过 HTML 解析器,无风险
- 例如:
el.textContent = `欢迎,${userName}!`;
必须插入 HTML(如富文本、Markdown 渲染)→ 用 DOMPurify 或构造法转义
- 轻量可靠方案(无依赖):
function htmlEscape(str) {<br> const el = document.createElement('div');<br> el.textContent = str;<br> return el.innerHTML;<br> }
再拼接:const safeHtml = <span title="${htmlEscape(title)}">${htmlEscape(content)}</span>; - 复杂 HTML → 用
DOMPurify.sanitize(dirtyHtml),配置白名单(如只允许p、strong、a[href])
用标签函数封装转义逻辑(推荐进阶用法)
把转义行为内聚到模板字符串调用环节,避免每次手动调用:
- 定义安全标签函数:
function safe(strings, ...values) {<br> return strings.reduce((acc, str, i) => {<br> const val = values[i] ?? '';<br> const escaped = htmlEscape(String(val));<br> return acc + str + escaped;<br> }, '');<br> } - 使用:
el.innerHTML = safe`<h2>${title}</h2> <p>${bio}</p>`; - 好处:语义清晰、复用性强、不易遗漏
服务端与前端转义不能互相替代
前后端各守一关:
- 服务端模板渲染前(如 Node.js 的 EJS、Python 的 Jinja):对所有用户数据调用
html.escape()或等效函数 - 前端动态更新时(如 fetch 后渲染):仍需用
textContent或htmlEscape()处理,不能假设“后端已转义就安全” - 特别注意:模板引擎默认行为不一致(Vue 的
{{ }}转义,v-html不转义;EJS 默认转义但不转义)
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











