
1. CSRF漏洞的本质与危害CSRFCross-Site Request Forgery是一种利用用户已登录状态发起的恶意请求攻击。想象这样一个场景你在咖啡厅用笔记本登录了银行网站此时浏览器保存了登录凭证。如果这时你点开了黑客发来的钓鱼邮件里的链接这个页面可能偷偷向银行发送转账请求——因为浏览器会自动带上你的登录凭证银行系统会认为这是你本人操作。这种攻击之所以危险是因为攻击者无需获取用户凭证用户完全无感知可执行任意权限范围内的操作攻击成本极低典型攻击流程用户登录受信任网站A网站A在用户浏览器设置认证Cookie用户未登出A的情况下访问恶意网站BB的页面包含自动向A发送请求的代码浏览器自动携带A的Cookie发送请求A服务器无法区分该请求是否来自用户真实意愿2. Spring Boot应用为何容易裸奔很多Spring Boot开发者存在以下误区误区一GET请求不需要防护GetMapping(/transfer) public String transferMoney(RequestParam String toAccount, RequestParam BigDecimal amount) { // 转账逻辑 }攻击者只需构造一个图片链接img srchttp://bank.com/transfer?toAccounthackeramount10000误区二POST请求天然安全form actionhttp://bank.com/transfer methodPOST input typehidden nametoAccount valuehacker input typehidden nameamount value10000 /form scriptdocument.forms[0].submit();/script误区三前后端分离无需考虑即使使用AJAX浏览器仍会自动携带Cookiefetch(/api/transfer, { method: POST, body: JSON.stringify({toAccount: hacker, amount: 10000}), headers: {Content-Type: application/json} })3. Spring Security防御方案全解析3.1 基础防护配置Configuration EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { Override protected void configure(HttpSecurity http) throws Exception { http .csrf() .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()) .and() // 其他配置... } }3.2 深度防御策略策略一CookieHeader双重验证.csrfTokenRepository(new CookieCsrfTokenRepository() {{ setCookieHttpOnly(false); // 允许JS读取 setCookieName(XSRF-TOKEN); setHeaderName(X-XSRF-TOKEN); }})策略二自定义防护路径.requireCsrfProtectionMatcher(request - { // 只保护/api开头的POST/PUT/DELETE请求 return request.getMethod().matches(POST|PUT|DELETE) request.getRequestURI().startsWith(/api); })策略三动态Token刷新.csrfTokenRepository(new CsrfTokenRepository() { Override public CsrfToken generateToken(HttpServletRequest request) { return new DefaultCsrfToken( X-CSRF-TOKEN, _csrf, UUID.randomUUID().toString() ); } // 其他实现方法... })4. 实战中的坑与解决方案坑一文件上传失效// 错误配置 http.csrf().disable(); // 正确方案 http.csrf().ignoringAntMatchers(/upload);坑二前后端分离场景前端需要从Cookie读取XSRF-TOKEN在每次请求Header中添加X-XSRF-TOKEN// Axios拦截器示例 axios.interceptors.request.use(config { const token document.cookie .split(; ) .find(row row.startsWith(XSRF-TOKEN)) ?.split()[1]; config.headers[X-XSRF-TOKEN] token; return config; });坑三多Tab操作冲突解决方案每个表单生成独立Tokenform input typehidden name_csrf th:value${csrfToken} !-- 表单内容 -- /form5. 高级防护技巧技巧一二次验证PostMapping(/transfer) public ResponseEntity? transfer( RequestParam String toAccount, RequestParam BigDecimal amount, CookieValue(value XSRF-TOKEN) String csrfToken, RequestHeader(X-XSRF-TOKEN) String headerToken) { if(!csrfToken.equals(headerToken)) { throw new InvalidCsrfTokenException(); } // 业务逻辑... }技巧二操作指纹绑定String userFingerprint request.getHeader(User-Agent) request.getHeader(Accept-Language); String storedToken redis.get(userFingerprint); if(!storedToken.equals(request.getHeader(X-CSRF-TOKEN))) { throw new InvalidCsrfTokenException(); }技巧三敏感操作限流RateLimiter(value 1, timeUnit TimeUnit.MINUTES) PostMapping(/transfer) public ResponseEntity? transferMoney() { // 业务逻辑 }6. 渗透测试常见问题问题一CSRF Token泄露通过子域名或XSS漏洞可能窃取Token解决方案.setCookieDomain(maindomain.com) // 限制Cookie域 .setSecure(true) // 仅HTTPS传输问题二Token未绑定会话// 错误做法所有用户使用相同Token String staticToken fixed_token_value; // 正确做法会话级Token String sessionToken UUID.randomUUID().toString(); request.getSession().setAttribute(CSRF_TOKEN, sessionToken);问题三防护覆盖不全检查清单[ ] 所有状态修改操作POST/PUT/DELETE/PATCH[ ] 文件上传接口[ ] GraphQL端点[ ] SOAP WebService[ ] 第三方回调接口7. Spring Security 6.x新特性特性一CSRF Token自动旋转.csrfTokenRepository(new RotatingCsrfTokenRepository())特性二同站点Cookie属性Bean public CookieSerializer cookieSerializer() { DefaultCookieSerializer serializer new DefaultCookieSerializer(); serializer.setSameSite(Strict); return serializer; }特性三安全头增强http.headers() .contentSecurityPolicy(script-src self) .xssProtection() .and() .referrerPolicy(ReferrerPolicy.SAME_ORIGIN);在实际项目中我建议采用分层防御策略基础CSRF防护敏感操作二次验证关键接口限流。曾经有个电商项目因为忽略CSRF防护导致攻击者利用图片外链批量修改用户收货地址这个教训让我在后续所有项目中都严格执行CSRF防护规范。