JSON本身不是脚本,但当携带恶意用户输入且前端不加转义直接插入DOM时,会触发存储型XSS;防护关键在于后端输出编码(如StringEscapeUtils.escapeHtml4)与前端按上下文安全插入(如Vue{{}}、React{}/JSON.stringify),并叠加CSP与白名单校验。

JSON 本身不是脚本,但当它携带用户输入内容、又被前端不加处理地插入 DOM 时,就可能触发存储型 XSS。防范关键不在 JSON 格式本身,而在于“数据如何从 JSON 流入页面”这个环节——重点是转义时机、上下文匹配和输出控制。
存储型 XSS 在 JSON 场景中的典型路径
攻击者提交恶意内容(如 <script>fetch('/steal?c='+document.cookie)</script>)→ 后端未过滤存入数据库 → 前端通过 Ajax 获取 JSON(如 {"content": "..."})→ 直接用 innerHTML 或 v-html 渲染 → 脚本执行。
整个链条里,JSON 是“运输工具”,真正危险的是渲染动作。所以防护必须覆盖后端输出编码 + 前端安全插入两个环节。
后端生成 JSON 时强制转义敏感字符
JavaWeb 等服务端在序列化 JSON 前,应对所有可能含用户输入的字段做 HTML 实体转义(不是 URL 编码,也不是 JS 字符串转义):
立即学习“Java免费学习笔记(深入)”;
- 对字段值中出现的
<、>、&、"、'进行 HTML 编码,例如<script>→<script></script> - 使用标准库而非手写正则:Java 推荐
StringEscapeUtils.escapeHtml4()(Apache Commons Text),Spring Boot 可配置@JsonSerialize自定义序列化器统一处理 - 避免仅靠前端过滤:后端转义是第一道防线,否则 JSON 可被其他客户端(如原生 App)直接消费并误解析
前端解析 JSON 后按上下文安全插入
拿到 JSON 数据后,绝不能无差别拼接或赋值给 innerHTML。必须区分插入位置,选择对应方式:
- 插入 HTML 内容区域(如评论正文)→ 使用框架默认转义机制:Vue 中用
{{ content }}(自动 HTML 转义),React 中用{content}(自动转义),禁用v-html/dangerouslySetInnerHTML除非内容已由后端清洗为可信富文本 - 插入 HTML 属性(如
title="{{ title }}")→ 先对值做属性级转义(引号、等号、尖括号均需处理),再放入双引号属性中;更稳妥做法是改用element.setAttribute('title', value),由浏览器自动处理 - 插入 JavaScript 字符串(如
var msg = "{{ content }}";)→ 必须用JSON.stringify()包裹,它会自动对反斜杠、引号、控制字符做 Unicode 转义,比手写replace()更可靠
补充两道加固层
仅靠转义还不够,建议叠加以下机制提升纵深防御能力:
- 启用 CSP(Content-Security-Policy)响应头,明确禁止内联脚本和
eval,即使 XSS 代码被注入也无法执行 - 对 JSON 接口返回的敏感字段(如
content、bio)增加服务端白名单校验,比如限制只允许中文、英文字母、常见标点,拒绝<script、onerror=、javascript:等模式 - 前端加载 JSON 后,可用简单正则快速检测高危特征(如
/<[sS]*?script/i.test(data.content)),发现即丢弃或告警,作为兜底策略


















