如何在PUG中正确解析MongoDB存储的双重转义HTML内容
解决方案
问题根源
你存储在MongoDB中的内容是双重HTML编码的结果:
- 第一次编码将原始HTML中的特殊字符(如
<)转义为< - 第二次编码又将第一次生成的
&转义为&,最终形成你看到的&lt;格式
现有写法的问题
- 使用
!{exhibitor.profile}时,PUG会跳过输出转义,仅解开第二层编码,得到单层编码的<div>这类内容,浏览器会将其识别为普通文本,不会解析成HTML标签 - 使用
#{exhibitor.profile}时,PUG会在输出时额外做一次HTML编码,等于在双重编码基础上又加了一层,和原始存储内容一致,更无法解析
修复方案
推荐优先在服务端处理后再传递给PUG模板,以Node.js环境为例:
- 引入HTML编解码工具库
he,或使用原生逻辑实现解码能力 - 对数据库取出的内容连续做2次HTML解码
- PUG模板中使用
!{}输出解码后的内容即可
示例代码:
服务端预处理代码
const he = require('he'); // 从MongoDB查询到数据后执行两次解码 exhibitor.profile = he.decode(he.decode(exhibitor.profile));
PUG模板代码
.exhibitor-profile | !{exhibitor.profile}
如果希望在前端处理,也可以用原生JS实现解码后再插入DOM:
function decodeHtml(raw) { const temp = document.createElement('textarea'); temp.innerHTML = raw; return temp.value; } // 两次解码后插入到页面 const rawProfile = '/* 从接口获取的原始编码内容 */'; const decoded = decodeHtml(decodeHtml(rawProfile)); document.querySelector('.exhibitor-profile').innerHTML = decoded;
安全提示:直接渲染未经过滤的用户提交HTML存在XSS注入风险,建议解码后先对HTML内容做标签、属性白名单过滤,再渲染到页面
内容的提问来源于stack exchange,提问作者Alim Bolar
相关产品推荐
相关产品推荐

