
HTML表单提交前必须做输入转义
用户在 <input>、<textarea></textarea> 里输的内容,直接拼进 HTML 页面(比如回显、提示语、服务端渲染结果)就会触发 XSS。关键不是“表单本身防不防”,而是你把用户数据放哪儿、怎么放。
常见错误现象:<div>欢迎,<script>alert(1)</script>
</div> 这种回显导致脚本执行;或者用 innerHTML = userInput 动态插入内容。
- 服务端渲染场景:对所有用户输入字段,在插入 HTML 前必须做 HTML 实体转义,比如
→ <code><,"→" - 前端 JS 渲染场景:禁用
innerHTML、document.write,改用textContent或框架自带的自动转义机制(如 React 的 JSX、Vue 的插值) - 别信“只过滤
<script></script>”——XSS 载荷可以藏在<img src="x" onerror="..." alt="HTML表单怎样防止XSS攻击_HTML表单防止XSS攻击步骤【教程】" >、<svg onload="..."></svg>甚至 CSS 中
form action 提交到后端时不能跳过服务端校验
前端加 onsubmit 拦截、用 preventDefault() 做 JS 校验,只是体验优化,完全挡不住绕过。攻击者删掉 JS、用 curl 直接 POST,你的表单就裸奔了。
使用场景:任何带 method="POST" 的表单,尤其登录、评论、资料修改等涉及用户输入落地的操作。
立即学习“前端免费学习笔记(深入)”;
- 服务端必须重新解析并校验
req.body(Node.js)、$_POST(PHP)、request.form(Flask)里的字段,不能信任前端传来的“已清洗”标记 - 校验不是只看长度或正则——比如邮箱正则再严,也拦不住
"onfocus="alert(1)" autofocus"这种注入到属性里的 payload - 如果后端用了模板引擎(如 EJS、Jinja2),确认是否默认开启自动转义;没开的话,每个变量插值都得手动写
类似逻辑
富文本编辑器场景下,白名单比黑名单更可靠
允许用户发带格式的评论、文章?这时候不能简单“过滤 script 标签”,因为 <style></style>、<iframe></iframe>、javascript: href、data: URI 都可能成为 XSS 入口。
性能 / 兼容性影响:纯正则黑名单容易漏、容易误杀,还可能被编码绕过(如 <script></script>);而白名单解析(如用 DOMPurify)虽有轻微开销,但确定性强。
- 不要自己写正则去 strip 标签——用成熟库:浏览器端用
DOMPurify.sanitize(dirtyHtml),服务端用bleach.clean()(Python)、js-xss(Node.js) - 配置白名单时明确指定允许的标签(
['b', 'i', 'p', 'a'])、属性(['href', 'title'])、协议(只允http/https,禁javascript:) - 即使用了净化库,也别把净化后的内容再用
innerHTML插入——有些库返回的是字符串,需确保插入方式安全(如先创建空div,再设innerHTML)
HTTP 头和 CSP 是最后一道防线,但不能替代代码层防护
X-XSS-Protection 在现代浏览器中基本废弃,Content-Security-Policy 才是当前最有效的兜底手段——但它只拦住执行,拦不住 DOM 注入本身。
容易踩的坑:CSP 配置太宽泛(如 script-src 'unsafe-inline')等于没设;或者只在首页加,忘了给 API 接口页或后台管理页配。
- 关键配置项至少包含:
default-src 'self'、script-src 'self' 'unsafe-eval'(慎加unsafe-inline)、style-src 'self' 'unsafe-inline' - CSP 的
report-uri或report-to要配好,否则出问题你根本不知道 - 注意:CSP 不解决存储型 XSS 的数据污染问题——它只让恶意脚本跑不起来,但脏数据依然存在数据库里,下次渲染还可能被其他路径触发
真正难的不是加几行 header,而是搞清每个输入点的数据流向:从表单进来,经过哪层处理,以什么方式落到 HTML、JS、CSS、URL、HTTP header 中——每个落点都要单独评估风险。漏掉一个,整条链就断了。











