chat
是什么?
好的,咱们把 XSS 攻击一次讲透,从“是什么 → 怎么发生 → 有哪些类型 → 有多危险 → 如何防 → 实战最佳实践”全程打通。
一、什么是 XSS?
XSS(Cross-Site Scripting,跨站脚本攻击) 简单说就是:
攻击者把恶意 JavaScript 注入到页面中,当其他用户访问页面时,这段脚本就在他们浏览器中执行。
本质: 浏览器“信任了不该信任的内容”,把用户输入当成了代码执行。
核心公式:
用户输入 → 未过滤 → 直接渲染到页面 → 浏览器执行
二、XSS 能干什么?(为什么危险)
XSS 不只是弹个 alert,它是真·高危漏洞:
| 能力 | 实际后果 |
|---|---|
| 读取 Cookie / Token | 劫持登录态,直接接管账号 |
| 模拟用户操作 | 自动发帖、转账、改资料 |
| 页面钓鱼 | 嵌入假登录框骗密码 |
| 远程加载木马 | 植入键盘记录,长期监控 |
| 绕过权限系统 | 构造后台请求 |
✅ 在企业系统里: XSS = 管理员权限沦陷 = 数据泄露 / 系统失控
三、XSS 的三大类型
1. 反射型 XSS(Reflected)
用户输入的数据立刻返回到页面中。
典型场景:
/search?keyword=<script>恶意代码</script>
页面直接渲染 keyword,就被执行。
特点:
- 需要诱导点击链接
- 不持久
- 常见于搜索、错误页面
2. 存储型 XSS(Stored)
恶意代码被存进数据库,所有访问者都会中招。
比如:
- 评论区
- 用户昵称
- 个人简介
攻击者提交:
<script>...</script>
后台存了,所有人加载页面就执行。
✅ 最危险的一种
3. DOM 型 XSS
不是后端问题,而是前端 JS 逻辑问题。
例如:
document.getElementById("box").innerHTML = location.hash;
攻击者构造 URL:
http://xxx.com/#<script>代码</script>
浏览器自己执行,服务器完全不知情。
四、XSS 常见触发点
🚩 高危位置:
- v-html
- innerHTML
- eval()
- setTimeout(“字符串”)
- new Function()
- document.write()
- location.href 动态拼接
🚩 高风险输入源:
- URL 参数
- 表单内容
- 评论、富文本
- Cookie
- localStorage
- WebSocket 推送
五、典型 XSS 漏洞示例
危险写法(Vue):
<div v-html="userInput"></div>
如果 userInput = <script>steal()</script>
你网页就变攻击平台了。
危险写法(JS):
element.innerHTML = userContent;
六、XSS 防御核心原则
一句话总结:
所有用户输入都是不可信的 所有输出都必须转义
四大防御策略:
- ✅ 输出时统一转义(核心)
- ✅ 不信任任何输入
- ✅ 避免动态执行 JS
- ✅ 强制 CSP 内容安全策略
七、XSS 防御的黄金公式
✅ 正确思想
| 场景 | 正确做法 |
|---|---|
| 普通文本 | 转义显示 |
| HTML内容 | 白名单过滤 |
| JSON数据 | 严格序列化 |
| URL | encodeURIComponent |
八、前端 Vue3 防 XSS 实战
1. 永远避免 v-html
❌ 错误:
<div v-html="content"></div>
✅ 安全:
<div><!-- Post Header -->
<header class="intro-header" style="background-image: url('/static/app/res/img/home-bg.jpeg')" >
<div class="container">
<div class="row">
<div class="col-lg-10 col-lg-offset-1 col-md-10 col-md-offset-1">
<div class="post-heading">
<div class="tags">
<a class="tag" href="/tags/#plateform" title="plateform">plateform</a>
<a class="tag" href="/tags/#sh" title="sh">sh</a>
</div>
<h1>权限体系之-20-passport 安全攻击有哪些?</h1>
<h2 class="subheading"></h2>
<span class="meta">
Posted by
<a class="my-aw" href="/about/">houbb</a>
on November 20, 2025
</span>
</div>
</div>
</div>
</div>
</header>
<article class="post" itemscope itemtype="http://schema.org/BlogPosting">
<div class="container" style="overflow-y:hidden;">
<div class="row">
<div class="col-lg-10 col-lg-offset-1 col-md-10 col-md-offset-1 post-container">
<div class="post-content" itemprop="articleBody" style="min-height: 420px;">
<h1 id="chat">chat</h1>
<h2 id="类似-xss-的攻击有哪些">类似 XSS 的攻击有哪些?</h2>
<p>很好,这个问题问得非常“安全架构层级” 👍
如果说 <strong>XSS 是前端最典型的注入攻击</strong>,那它只是冰山一角。和 XSS 同一“家族”的攻击,其实是一个完整的攻击谱系。</p>
<p>我给你按「攻击本质」分类,帮你建立一套安全认知地图。</p>
<hr />
<h1 id="一和-xss-同级的注入类攻击最危险家族">一、和 XSS 同级的“注入类攻击”(最危险家族)</h1>
<p>它们的共同点:</p>
<blockquote>
<p>把恶意内容当成指令执行</p>
</blockquote>
<h2 id="1-sql-注入sql-injection">1. SQL 注入(SQL Injection)</h2>
<p>把用户输入拼接进 SQL 语句。</p>
<p>例子原理:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>用户名: admin' OR '1'='1
</code></pre></div></div>
<p>危害:</p>
<ul>
<li>数据库被拖库</li>
<li>数据篡改</li>
<li>权限绕过</li>
</ul>
<p>✅ 防御:</p>
<ul>
<li>PreparedStatement</li>
<li>ORM 参数绑定</li>
<li>禁止字符串拼接 SQL</li>
</ul>
<hr />
<h2 id="2-os-命令注入command-injection">2. OS 命令注入(Command Injection)</h2>
<p>攻击者让服务器执行系统命令:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>; rm -rf /
</code></pre></div></div>
<p>常见场景:</p>
<ul>
<li>调用 shell 执行命令</li>
<li>文件处理系统</li>
</ul>
<p>✅ 防御:</p>
<ul>
<li>禁止拼接 shell 命令</li>
<li>使用白名单参数</li>
<li>最小权限原则</li>
</ul>
<hr />
<h2 id="3-ldap-注入">3. LDAP 注入</h2>
<p>类似 SQL,只不过目标是 LDAP 目录服务。</p>
<p>危害:</p>
<ul>
<li>绕过认证</li>
<li>获取组织架构、用户信息</li>
</ul>
<hr />
<h2 id="4-xpath-注入">4. XPath 注入</h2>
<p>针对 XML 查询语言的注入攻击:</p>
<ul>
<li>常见于老系统、政企系统</li>
</ul>
<hr />
<h1 id="二web-权限类攻击">二、Web 权限类攻击</h1>
<h2 id="5-csrf跨站请求伪造">5. CSRF(跨站请求伪造)</h2>
<p>伪造用户身份发请求:</p>
<p>场景:
用户登录状态下访问恶意网站 → 自动向你系统发请求。</p>
<p>危险操作:</p>
<ul>
<li>转账</li>
<li>修改密码</li>
<li>删除数据</li>
</ul>
<p>✅ 防御:</p>
<ul>
<li>CSRF Token</li>
<li>SameSite Cookie</li>
<li>Referer 校验</li>
</ul>
<hr />
<h2 id="6-idor越权访问">6. IDOR(越权访问)</h2>
<p>直接修改参数获取他人数据:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/api/order?id=10001 → 改成 10002
</code></pre></div></div>
<p>危害:</p>
<ul>
<li>任意查看他人数据</li>
<li>修改他人资源</li>
</ul>
<p>✅ 防御:</p>
<ul>
<li>每次校验当前用户权限</li>
<li>不能只靠前端控制</li>
</ul>
<hr />
<h2 id="7-逻辑漏洞攻击">7. 逻辑漏洞攻击</h2>
<p>利用业务规则盲区:</p>
<ul>
<li>重复领取优惠券</li>
<li>越界操作</li>
<li>多次退款</li>
</ul>
<p>这是安全中最难防的一类,非常常见。</p>
<hr />
<h1 id="三浏览器与前端相关攻击">三、浏览器与前端相关攻击</h1>
<h2 id="8-clickjacking点击劫持">8. Clickjacking(点击劫持)</h2>
<p>覆盖透明 iframe,引诱用户点击:</p>
<ul>
<li>用户以为点 A,实际上点 B</li>
</ul>
<p>✅ 防御:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>X-Frame-Options: DENY
</code></pre></div></div>
<hr />
<h2 id="9-dom-型攻击">9. DOM 型攻击</h2>
<p>类似 XSS,但在浏览器 JS 中产生:</p>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">location</span><span class="p">.</span><span class="nx">hash</span> <span class="nx">注入</span>
<span class="nx">innerHTML</span> <span class="nx">拼接</span>
</code></pre></div></div>
<hr />
<h1 id="四会话与身份攻击">四、会话与身份攻击</h1>
<h2 id="10-session-劫持">10. Session 劫持</h2>
<p>通过:</p>
<ul>
<li>XSS + Cookie 窃取</li>
<li>网络中间人</li>
</ul>
<p>✅ 防御:</p>
<ul>
<li>HttpOnly</li>
<li>Secure Cookie</li>
<li>HTTPS</li>
</ul>
<hr />
<h2 id="11-重放攻击replay">11. 重放攻击(Replay)</h2>
<p>截获请求包重复发送。</p>
<p>常见于:</p>
<ul>
<li>登录</li>
<li>支付接口</li>
</ul>
<p>✅ 防御:</p>
<ul>
<li>nonce + timestamp</li>
<li>请求签名</li>
</ul>
<hr />
<h2 id="12-暴力破解--撞库">12. 暴力破解 & 撞库</h2>
<ul>
<li>密码组合爆破</li>
<li>数据库泄露后的账号尝试</li>
</ul>
<p>✅ 防御:</p>
<ul>
<li>登录限流</li>
<li>验证码</li>
<li>失败锁定</li>
</ul>
<hr />
<h1 id="五供应链攻击">五、供应链攻击</h1>
<h2 id="13-依赖投毒">13. 依赖投毒</h2>
<p>篡改第三方库代码:</p>
<ul>
<li>NPM 后门事件</li>
<li>OpenSSL 漏洞</li>
</ul>
<p>✅ 防御:</p>
<ul>
<li>依赖审计</li>
<li>锁版本</li>
<li>SBOM</li>
</ul>
<hr />
<h1 id="六文件与上传攻击">六、文件与上传攻击</h1>
<h2 id="14-文件上传漏洞">14. 文件上传漏洞</h2>
<p>上传:</p>
<ul>
<li>WebShell</li>
<li>木马脚本</li>
</ul>
<p>✅ 防御:</p>
<ul>
<li>严格限制扩展名</li>
<li>MIME 验证</li>
<li>存储隔离</li>
</ul>
<hr />
<h1 id="七信息泄露类攻击">七、信息泄露类攻击</h1>
<h2 id="15-敏感信息泄露">15. 敏感信息泄露</h2>
<ul>
<li>配置文件暴露</li>
<li>日志打印密码</li>
<li>接口直接返回密钥</li>
</ul>
<hr />
<h1 id="八综合对比xss-在攻击体系中的位置">八、综合对比:XSS 在攻击体系中的位置</h1>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>安全攻击谱系图:
注入类:
├── XSS
├── SQL Injection
├── Command Injection
└── LDAP 注入
会话类:
├── CSRF
├── Session Hijacking
└── Replay
授权类:
├── IDOR
└── 越权访问
客户端类:
├── Clickjacking
└── DOM-based 攻击
</code></pre></div></div>
<hr />
<h1 id="九企业级常见-top-10-攻击实战高频">九、企业级常见 Top 10 攻击(实战高频)</h1>
<p>来自 OWASP Top 10 常见组合:</p>
<ol>
<li>XSS</li>
<li>SQL 注入</li>
<li>CSRF</li>
<li>文件上传漏洞</li>
<li>未授权访问</li>
<li>逻辑漏洞</li>
<li>会话固定</li>
<li>信息泄露</li>
<li>SSRF</li>
<li>依赖组件漏洞</li>
</ol>
<hr />
<h1 id="十你该如何构建系统级防护">十、你该如何构建系统级防护</h1>
<p>如果你是做平台架构,我建议建立四层安全体系:</p>
<table>
<thead>
<tr>
<th>层级</th>
<th>防护重点</th>
</tr>
</thead>
<tbody>
<tr>
<td>前端</td>
<td>输入过滤 + CSP</td>
</tr>
<tr>
<td>接口</td>
<td>参数校验 + Token</td>
</tr>
<tr>
<td>服务</td>
<td>权限控制 + 认证</td>
</tr>
<tr>
<td>数据</td>
<td>加密 + 审计</td>
</tr>
</tbody>
</table>
<hr />
<h1 id="简单总结">简单总结</h1>
<p>可以把“类似 XSS 的攻击”理解为:</p>
<blockquote>
<p>一切把数据当代码执行的攻击
一切利用用户信任和系统漏洞的攻击</p>
</blockquote>
<p>XSS = 浏览器执行代码
SQL 注入 = 数据库执行代码
命令注入 = 操作系统执行代码</p>
<p>本质都是:<strong>执行了不该执行的东西</strong></p>
<ul id="markdown-toc">
<li><a href="#chat" id="markdown-toc-chat">chat</a> <ul>
<li><a href="#类似-xss-的攻击有哪些" id="markdown-toc-类似-xss-的攻击有哪些">类似 XSS 的攻击有哪些?</a></li>
</ul>
</li>
<li><a href="#一和-xss-同级的注入类攻击最危险家族" id="markdown-toc-一和-xss-同级的注入类攻击最危险家族">一、和 XSS 同级的“注入类攻击”(最危险家族)</a> <ul>
<li><a href="#1-sql-注入sql-injection" id="markdown-toc-1-sql-注入sql-injection">1. SQL 注入(SQL Injection)</a></li>
<li><a href="#2-os-命令注入command-injection" id="markdown-toc-2-os-命令注入command-injection">2. OS 命令注入(Command Injection)</a></li>
<li><a href="#3-ldap-注入" id="markdown-toc-3-ldap-注入">3. LDAP 注入</a></li>
<li><a href="#4-xpath-注入" id="markdown-toc-4-xpath-注入">4. XPath 注入</a></li>
</ul>
</li>
<li><a href="#二web-权限类攻击" id="markdown-toc-二web-权限类攻击">二、Web 权限类攻击</a> <ul>
<li><a href="#5-csrf跨站请求伪造" id="markdown-toc-5-csrf跨站请求伪造">5. CSRF(跨站请求伪造)</a></li>
<li><a href="#6-idor越权访问" id="markdown-toc-6-idor越权访问">6. IDOR(越权访问)</a></li>
<li><a href="#7-逻辑漏洞攻击" id="markdown-toc-7-逻辑漏洞攻击">7. 逻辑漏洞攻击</a></li>
</ul>
</li>
<li><a href="#三浏览器与前端相关攻击" id="markdown-toc-三浏览器与前端相关攻击">三、浏览器与前端相关攻击</a> <ul>
<li><a href="#8-clickjacking点击劫持" id="markdown-toc-8-clickjacking点击劫持">8. Clickjacking(点击劫持)</a></li>
<li><a href="#9-dom-型攻击" id="markdown-toc-9-dom-型攻击">9. DOM 型攻击</a></li>
</ul>
</li>
<li><a href="#四会话与身份攻击" id="markdown-toc-四会话与身份攻击">四、会话与身份攻击</a> <ul>
<li><a href="#10-session-劫持" id="markdown-toc-10-session-劫持">10. Session 劫持</a></li>
<li><a href="#11-重放攻击replay" id="markdown-toc-11-重放攻击replay">11. 重放攻击(Replay)</a></li>
<li><a href="#12-暴力破解--撞库" id="markdown-toc-12-暴力破解--撞库">12. 暴力破解 & 撞库</a></li>
</ul>
</li>
<li><a href="#五供应链攻击" id="markdown-toc-五供应链攻击">五、供应链攻击</a> <ul>
<li><a href="#13-依赖投毒" id="markdown-toc-13-依赖投毒">13. 依赖投毒</a></li>
</ul>
</li>
<li><a href="#六文件与上传攻击" id="markdown-toc-六文件与上传攻击">六、文件与上传攻击</a> <ul>
<li><a href="#14-文件上传漏洞" id="markdown-toc-14-文件上传漏洞">14. 文件上传漏洞</a></li>
</ul>
</li>
<li><a href="#七信息泄露类攻击" id="markdown-toc-七信息泄露类攻击">七、信息泄露类攻击</a> <ul>
<li><a href="#15-敏感信息泄露" id="markdown-toc-15-敏感信息泄露">15. 敏感信息泄露</a></li>
</ul>
</li>
<li><a href="#八综合对比xss-在攻击体系中的位置" id="markdown-toc-八综合对比xss-在攻击体系中的位置">八、综合对比:XSS 在攻击体系中的位置</a></li>
<li><a href="#九企业级常见-top-10-攻击实战高频" id="markdown-toc-九企业级常见-top-10-攻击实战高频">九、企业级常见 Top 10 攻击(实战高频)</a></li>
<li><a href="#十你该如何构建系统级防护" id="markdown-toc-十你该如何构建系统级防护">十、你该如何构建系统级防护</a></li>
<li><a href="#简单总结" id="markdown-toc-简单总结">简单总结</a></li>
</ul>
</div>
<div class="more-learn-wrapper">
<h2 id="更多学习">更多学习</h2>
<li>
<a class="my-a" href="https://github.com/houbb"><span class="icon icon--github"><svg viewBox="0 0 16 16"><path fill="#828282" d="M7.999,0.431c-4.285,0-7.76,3.474-7.76,7.761 c0,3.428,2.223,6.337,5.307,7.363c0.388,0.071,0.53-0.168,0.53-0.374c0-0.184-0.007-0.672-0.01-1.32 c-2.159,0.469-2.614-1.04-2.614-1.04c-0.353-0.896-0.862-1.135-0.862-1.135c-0.705-0.481,0.053-0.472,0.053-0.472 c0.779,0.055,1.189,0.8,1.189,0.8c0.692,1.186,1.816,0.843,2.258,0.645c0.071-0.502,0.271-0.843,0.493-1.037 C4.86,11.425,3.049,10.76,3.049,7.786c0-0.847,0.302-1.54,0.799-2.082C3.768,5.507,3.501,4.718,3.924,3.65 c0,0,0.652-0.209,2.134,0.796C6.677,4.273,7.34,4.187,8,4.184c0.659,0.003,1.323,0.089,1.943,0.261 c1.482-1.004,2.132-0.796,2.132-0.796c0.423,1.068,0.157,1.857,0.077,2.054c0.497,0.542,0.798,1.235,0.798,2.082 c0,2.981-1.814,3.637-3.543,3.829c0.279,0.24,0.527,0.713,0.527,1.437c0,1.037-0.01,1.874-0.01,2.129 c0,0.208,0.14,0.449,0.534,0.373c3.081-1.028,5.302-3.935,5.302-7.362C15.76,3.906,12.285,0.431,7.999,0.431z"/></svg>
</span> 个人 Github</a>
</li>
<li>
<i class="fa fa-fw fa-wechat text-muted" title="wechat"></i> 个人公众号
</li>
<p>更多实时资讯,前沿技术,生活趣事。尽在【老马啸西风】</p>
<p>交流社群:<a href="https://mp.weixin.qq.com/s/rkSvXxiiLGjl3S-ZOZCr0Q">交流群信息</a></p>
<p><img src="/SIGN.png" alt="image" /></p>
</div>
<!--文章上下篇 START-->
<nav class="article-page-warp" style="margin-top: 20px;">
<div class="pagination-list">
<a class="prev pull-left my-a" href="/2025/11/20/sso-21-passport-log4j2" rel="bookmark">
<i class="fa fa-angle-left"></i> 权限体系之-21-passport springboot 整合 log4j2
</a>
<a class="next pull-right my-a" href="/2025/11/20/sso-31-passport-safe-security-xss" rel="bookmark">
权限体系之-20-passport 安全之 XSS <i class="fa fa-angle-right"></i>
</a>
</div>
</nav>
<!--文章上下篇 END-->
</div>
</div>
</div>
</article>
</div>
Vue 默认会自动转义。
2. 使用 DOMPurify(专业级过滤)
npm install dompurify
import DOMPurify from 'dompurify'
const safeHtml = DOMPurify.sanitize(dirtyHtml);
配合 v-html 才可安全使用。
3. 禁止使用 eval / new Function
任何动态 JS 字符串执行 = XSS 温床。
九、后端 Spring Boot 防御方案
1. 全局 XSS Filter(推荐)
@Component
@WebFilter(urlPatterns = "/*")
public class XssFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
chain.doFilter(new XssHttpServletRequestWrapper((HttpServletRequest) request), response);
}
}
配合 Wrapper 过滤:
public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
public XssHttpServletRequestWrapper(HttpServletRequest request) {
super(request);
}
@Override
public String getParameter(String name) {
String value = super.getParameter(name);
return HtmlUtils.htmlEscape(value);
}
}
2. JSON 输出防护
配置 Jackson:
@Bean
public ObjectMapper objectMapper() {
ObjectMapper mapper = new ObjectMapper();
mapper.getFactory().setCharacterEscapes(new HtmlCharacterEscapes());
return mapper;
}
十、浏览器层防护:CSP(最强防线)
HTTP 头:
Content-Security-Policy:
default-src 'self';
script-src 'self';
object-src 'none';
Spring Boot 配置:
http.headers().contentSecurityPolicy(
"default-src 'self'; script-src 'self'; object-src 'none';"
);
效果:
- 禁止页面执行外部恶意脚本
- 阻断内联脚本
十一、完整防御体系推荐
✅ 前端
- 禁用 v-html
- DOMPurify 清洗富文本
- 路由参数统一 encode
- 不拼接 HTML
✅ 后端
- XSS Filter 全局过滤
- Controller 参数校验
- 默认 HTML escape
✅ 浏览器
- CSP
- HttpOnly Cookie
- SameSite
十二、推荐的综合最佳实践
✅ 最安全组合
| 层级 | 防护 |
|---|---|
| Vue | 自动转义显示 |
| API | HTML Escape 处理 |
| Header | CSP 强制策略 |
| Cookie | HttpOnly + Secure |
十三、简单总结(白话版)
XSS 就是别人把代码塞到你页面里,然后借你的系统攻击你的用户。
防御核心只有一句话:
✅ 不信任任何用户输入 ✅ 永远不要直接渲染未处理的内容 ✅ 所有输出必须经过转义或清洗
落地方案
明白,我给你整理一套 Spring Boot + Vue3 企业级防 XSS 攻击完整配置,覆盖前端、后端、浏览器策略,企业级可直接落地。我们按层级拆解:
一、前端 Vue3 防 XSS
1️⃣ 避免 v-html
❌ 错误写法:
<div v-html="userInput"></div>
✅ 安全写法:
<div></div>
- Vue3 默认会自动对 `` 插值进行 HTML 转义。
2️⃣ 富文本或 HTML 内容需要安全处理
使用 DOMPurify 过滤用户输入的 HTML:
npm install dompurify
import DOMPurify from 'dompurify'
const safeHtml = DOMPurify.sanitize(dirtyHtml, {
ALLOWED_TAGS: ['b','i','u','p','br','ul','li','a','img'],
ALLOWED_ATTR: ['href','src','alt','title']
})
然后再渲染:
<div v-html="safeHtml"></div>
✅ 注意:
- 不允许直接执行 JS(如
onerror、onclick等事件) - ALLOWED_TAGS/ATTR 可根据业务精简
3️⃣ URL 参数处理
const keyword = encodeURIComponent(route.query.keyword)
- 防止反射型 XSS
4️⃣ 避免动态执行 JS
// 不安全
eval(userInput)
new Function(userInput)
二、后端 Spring Boot 防 XSS
1️⃣ 全局 XSS Filter
import jakarta.servlet.*;
import jakarta.servlet.annotation.WebFilter;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.util.HtmlUtils;
import java.io.IOException;
@Component
@WebFilter(urlPatterns = "/*")
public class XssFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
chain.doFilter(new XssHttpServletRequestWrapper((HttpServletRequest) request), response);
}
}
Wrapper 对用户输入统一转义
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletRequestWrapper;
import org.springframework.web.util.HtmlUtils;
public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
public XssHttpServletRequestWrapper(HttpServletRequest request) {
super(request);
}
@Override
public String getParameter(String name) {
String value = super.getParameter(name);
return value != null ? HtmlUtils.htmlEscape(value) : null;
}
@Override
public String[] getParameterValues(String name) {
String[] values = super.getParameterValues(name);
if (values == null) return null;
for (int i = 0; i < values.length; i++) {
values[i] = HtmlUtils.htmlEscape(values[i]);
}
return values;
}
@Override
public String getHeader(String name) {
String value = super.getHeader(name);
return value != null ? HtmlUtils.htmlEscape(value) : null;
}
}
2️⃣ JSON 输出统一转义
import com.fasterxml.jackson.core.io.CharacterEscapes;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class JacksonConfig {
@Bean
public ObjectMapper objectMapper() {
ObjectMapper mapper = new ObjectMapper();
mapper.getFactory().setCharacterEscapes(new HtmlCharacterEscapes());
return mapper;
}
static class HtmlCharacterEscapes extends CharacterEscapes {
private final int[] asciiEscapes;
public HtmlCharacterEscapes() {
asciiEscapes = standardAsciiEscapesForJSON();
asciiEscapes['<'] = CharacterEscapes.ESCAPE_STANDARD;
asciiEscapes['>'] = CharacterEscapes.ESCAPE_STANDARD;
asciiEscapes['&'] = CharacterEscapes.ESCAPE_STANDARD;
asciiEscapes['"'] = CharacterEscapes.ESCAPE_STANDARD;
asciiEscapes['\''] = CharacterEscapes.ESCAPE_STANDARD;
}
@Override
public int[] getEscapeCodesForAscii() {
return asciiEscapes;
}
@Override
public SerializableString getEscapeSequence(int ch) {
return null;
}
}
}
✅ 这样返回给前端的 JSON 自动转义 <, >, ', " 等特殊字符,防止注入。
3️⃣ CSP(Content Security Policy)安全头
在 Spring Security 中设置:
http.headers()
.contentSecurityPolicy("default-src 'self'; script-src 'self'; object-src 'none'; style-src 'self'; img-src 'self' data:;")
.and()
.xssProtection(xss -> xss.block(true));
default-src 'self':默认只允许本域名资源script-src 'self':禁止加载外部 JSobject-src 'none':禁止 Flash/插件执行style-src 'self':只允许本地样式img-src 'self' data::允许 base64 图片
4️⃣ Cookie 安全策略
response.setHeader("Set-Cookie", "SESSION=xxx; HttpOnly; Secure; SameSite=Strict");
- 防止 XSS 偷 Cookie
三、前后端综合防护流程
-
前端:
- 避免 v-html
- 富文本过滤 DOMPurify
- URL 参数 encode
- 不动态执行 JS
-
后端:
- XSS Filter 全局参数转义
- JSON 输出转义
- 富文本可用 Jsoup/HTML Sanitizer 做白名单过滤
-
浏览器:
- CSP 强制策略
- HttpOnly + Secure Cookie
- SameSite Cookie
