模板字符串本身不防xss,安全关键在于如何处理用户数据;未过滤的用户输入直接插入${}并赋值给innerhtml会导致xss,应优先使用textcontent显示纯文本。

模板字符串本身不防XSS,安全的关键不是“怎么写模板”,而是“怎么处理用户数据”。直接把未处理的用户输入放进${}里再塞进innerHTML,等于给攻击者开后门。
优先用 textContent 而不是 innerHTML
如果只是显示文字(比如用户名、评论内容、提示信息),根本不需要生成 HTML 字符串。直接赋值给textContent,浏览器自动当纯文本处理,、<code>&、" 全部原样显示,不会被解析成标签或脚本。
- ✅ 安全写法:
el.textContent = `欢迎,${userName}`; - ❌ 危险写法:
el.innerHTML = `<p>欢迎,${userName}</p><div class="aritcle_card flexRow artxards"> <div class="artcardd flexRow"> <a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill6712" title="Wechat HTML Publisher"><img src="https://img.php.cn/upload/skill/000/000/081/179109368394970.jpg" alt="Wechat HTML Publisher" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a> <div class="aritcle_card_info flexColumn"> <a rel="nofollow" href="/xiazai/skill6712" title="Wechat HTML Publisher" class="overflowclass">Wechat HTML Publisher</a> <p class="overflowclass">直接上传HTML富文本到微信公众号草稿箱。支持完整的HTML格式,无需Markdown转换。</p> </div> <a rel="nofollow" href="/xiazai/skill6712" title="Wechat HTML Publisher" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span> </a> </div> </div>`;(哪怕 userName 看起来只是“张三”)
必须拼 HTML 时,先转义再插入
只有在确实需要动态生成带标签的结构(比如渲染一个用户头像+昵称卡片)时,才考虑模板字符串拼接。但前提是:所有来自用户的变量,都得提前做 HTML 实体编码。
- 别手写正则替换,容易漏掉
'或 Unicode 变体 - 用浏览器原生方式最可靠:
document.createElement('div').textContent = str; return div.innerHTML; - 转义后才能放进模板:
<div class="card">${escapeHtml(name)}</div>
更推荐:用 DOM API 代替字符串拼接
比起拼一长串 HTML 字符串,用document.createElement + textContent + appendChild更清晰、更安全、也更容易维护。
- 创建元素:
const card = document.createElement('div'); - 设文本内容:
card.textContent = name;(自动安全) - 加类或属性:
card.className = 'user-card'; - 追加到页面:
container.appendChild(card);
富文本等特殊场景要另作处理
如果业务真要支持<b></b>、<p></p>这类格式(比如后台编辑器输出),模板字符串和简单转义都不够。这时应交由专业净化库(如 DOMPurify)处理,按白名单过滤标签和属性,而不是自己拼接或信任服务端返回的 HTML。
- 不要用
innerHTML = untrustedHtml - 不要用
v-html或dangerouslySetInnerHTML除非你完全掌控输入源 - 即使用了净化库,也要配合 CSP 响应头进一步限制脚本执行
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










