HTML 实体编码指南:让代码片段安全地显示出来
转义的目的不是「让内容变安全」,而是「让内容按字面显示」。这两件事经常被混为一谈,出事也多半出在这里。
什么时候需要转义
在博客或文档里贴一段 <div class="box">,不转义的话浏览器会把它当成真标签,页面上只剩一个盒子,代码消失了。把尖括号转成 < 和 > 之后,它才会作为文字显示出来。
模板里输出用户填的内容、邮件模板里拼一段 HTML、把富文本编辑器的结果写进静态页面,都属于同一类需求:这段内容要「被看到」,而不是「被执行」。判断标准很简单:你要的是文字效果,还是标签效果。
- 在页面上展示 HTML / XML 代码
- 模板输出用户输入的文字
- 邮件和静态页里拼接片段
五个字符,一个顺序
需要转的只有五个:& 变成 &、< 变成 <、> 变成 >、双引号变成 "、单引号变成 '。其中 & 必须最先处理,否则后面生成的 < 会被再转一次,变成 &lt;。
属性值一律用引号包起来,别写 <a title=点这里>。工具会把单引号转成 ',这样用单引号包裹的属性也不会被截断。中文、日文和 emoji 保持原样,输出仍然可读,不需要也不应该全部转成数字实体。
- 先转 &,再转其他四个
- 属性值始终加引号
- 中文和 emoji 保持原样,输出更可读
边界:转义不等于防 XSS
XSS 防护要求按上下文转义:HTML 正文、属性、JavaScript 字符串、CSS、URL 各有各的规则,只做一层 HTML 实体替换挡不住所有注入。真正的防线在服务端模板引擎和内容安全策略,这个工具只适合手工处理文本。
它也不是加密:实体是公开的映射,谁都能还原。别用实体去「隐藏」邮箱或密钥,那只是让复制多一步。若内容来自不可信来源,展示前仍要经过白名单清洗,光靠实体替换挡不住注入。
- 按上下文转义,不能只做一层
- 实体是公开映射,不是加密
- 不可信内容仍需白名单清洗
常见问题
为什么只转五个字符?
因为只有这五个在 HTML 里有语法含义:& 开始一个实体,尖括号界定标签,引号界定属性值。其他字符(包括中文)不需要转义,转了只会让源码更难读。
转义之后还需要防 XSS 吗?
需要。这里的转义只保证内容按文字显示,不覆盖 JavaScript 上下文、URL 参数和 CSS。防护要在服务端按输出位置做,并配合 CSP 和输入校验,不能指望一次替换。
中文和 emoji 要不要转成实体?
不需要。现代页面统一用 UTF-8,中文和 emoji 直接写最易读,工具也会保留它们。只有需要把内容塞进纯 ASCII 环境时,才考虑数字实体。
相关工具:HTML 实体编码