页面能展示用户提交的内容,也可能把攻击者的代码带进浏览器。制定跨站脚本攻击检测与防御策略时,关键不是单纯过滤几个字符,而是阻止不可信数据被当作可执行代码。下面从检测、编码和内容安全配置,拆解五个可操作的方法。
1. 先找出不可信数据进入页面的路径
跨站脚本攻击(XSS)常见于三种情况:攻击内容随请求返回并立即显示的反射型 XSS;内容保存后被其他用户访问时触发的存储型 XSS;以及前端 JavaScript 从地址栏、浏览器存储等位置读取数据,再写入页面造成的 DOM 型 XSS。检查时要追踪数据从来源到页面输出的位置,而不只是检查表单。
- 列出用户可控来源,如评论、昵称、富文本、URL 片段和本地存储。
- 搜索代码中的危险写入方式,例如 JavaScript 的 innerHTML、React 的 dangerouslySetInnerHTML、Vue 的 v-html。
- 用 OWASP ZAP 等工具对测试环境进行扫描,再人工检查扫描结果是否能在浏览器中形成可执行内容。自动化扫描适合发现常见问题,但无法保证覆盖所有页面状态和业务流程。
2. 按输出位置进行上下文编码
输出编码是主要防线之一,但必须根据数据所在位置选择方式。普通 HTML 文本中的尖括号应编码为文本;放进 HTML 属性时,还要处理引号等特殊字符;进入 JavaScript、CSS 或 URL 时,则需要相应的上下文处理。把同一套替换规则套用到所有位置,可能留下漏洞,也可能破坏正常内容。
例如,评论内容应以普通文本方式显示,不能直接拼接进 HTML。若产品确实需要支持加粗等富文本,应使用经过维护的 HTML 清理库(如 DOMPurify),并明确允许的标签和属性;清理后也不要再把结果拼接到脚本或样式中。
3. 优先使用安全的页面渲染方式
能显示纯文本时,使用 textContent 或框架提供的默认转义模板,让浏览器把输入当作文字,而不是 HTML。React 和 Vue 通常会对常规模板插值进行转义,但显式插入原始 HTML 的接口会绕开这层保护。审查此类接口时,应确认内容经过可信的清理流程,并限制调用范围。
富文本编辑器、用户头像说明和评论列表都是容易出现差异的场景:先区分“允许展示格式”和“允许执行代码”,只开放业务确实需要的格式,避免为了省事直接接受完整 HTML。
4. 配置内容安全策略,降低漏洞后果
内容安全策略(CSP)可限制浏览器从哪些来源加载脚本,并减少内联脚本执行带来的风险。较稳妥的做法是逐步收紧脚本来源,优先采用随机 nonce 或哈希授权需要的脚本,避免长期依赖宽泛的 unsafe-inline。上线前可先使用报告模式观察被拦截的资源,再修正规则;具体配置取决于页面使用的脚本、第三方组件和浏览器支持情况。
CSP 是纵深防护,不是修复漏洞的替代品。若页面仍把未编码内容写入危险位置,策略配置错误或授权范围过宽时,攻击仍可能成功。
5. 把检查纳入开发与发布流程
- 为输入、存储、展示链路补充测试,覆盖普通文本、带标记的文本以及富文本允许的边界。
- 在代码审查中重点检查原始 HTML 插入、动态脚本和模板转义被关闭的地方。
- 在测试环境运行扫描,并用浏览器开发者工具确认异常内容最终是文字还是可执行节点。
- 发布后持续查看 CSP 报告和安全告警;修复问题时同时检查同类组件,防止只补单个页面。
常见问题
只过滤 script 标签够吗?
不够。事件属性、危险 URL 和 DOM 写入方式也可能造成脚本执行,且攻击载荷会变化;优先做上下文编码和安全渲染。

有了 CSP 还需要输出编码吗?
需要。CSP 用于限制脚本执行来源,输出编码用于避免数据被解析成代码,两者解决的问题不同。
富文本一定要禁止吗?
不一定。可采用允许列表清理,只保留业务所需的标签与属性,并在清理后按安全方式展示。
有效的跨站脚本攻击检测与防御策略,应把数据流检查、上下文编码、安全渲染和 CSP 配置结合起来。先消除危险输出点,再用扫描和发布检查持续验证,才能同时降低漏洞出现概率与被利用后的影响。


