SpringSecurity当中的CSRF防范详解

CSRF防范

什么是CSER

以下是基于 CSRF 攻击过程的 顺序图 及详细解释,结合多个技术文档中的攻击流程:


CSRF 攻击顺序图
用户 浏览器 受信任网站A 恶意网站B 正常操作阶段 访问网站A并登录 发送登录请求 返回登录成功的Cookie 存储Cookie(保持会话) 攻击触发阶段 访问恶意网站B(如点击链接) 请求页面 返回包含恶意代码的页面(如自动提交表单的JS) 伪造请求执行阶段 自动携带Cookie发送恶意请求(如转账) 验证Cookie合法,执行请求 用户未感知到操作已被篡改 用户 浏览器 受信任网站A 恶意网站B


攻击过程分步解读

  1. 用户登录受信任网站A
    • 用户通过浏览器正常登录网站A(例如银行网站),服务器生成会话 Cookie 并返回给浏览器。

• 关键点:此时浏览器会存储该 Cookie,后续所有对网站A的请求都会自动携带此 Cookie(如 Set-Cookie: session_id=abc123)。

  1. 用户访问恶意网站B
    • 攻击者通过钓鱼链接、诱导广告等方式,诱使用户访问恶意网站B。

• 攻击代码示例(来自网页3):

html 复制代码
<!-- 恶意网站B的页面 -->
<img src="http://网站A/转账?to=攻击者&amount=1000">
<!-- 或通过JS自动提交表单 -->
<script>
  document.write('<form action="http://网站A/改密码" method="POST">');
  document.write('<input type="hidden" name="new_password" value="hacker123">');
  document.write('</form>');
  document.forms[0].submit();
</script>
  1. 浏览器自动发送伪造请求
    • 恶意网站B的代码会触发浏览器向网站A发送请求(如转账、修改密码),浏览器会自动携带用户已登录的 Cookie。

• 服务器视角:网站A收到请求后,验证 Cookie 合法,误认为是用户主动操作,执行恶意请求。

  1. 攻击完成
    • 用户未感知到任何异常(如无页面跳转),但敏感操作已被执行(如资金转移、密码重置)。

攻击成功的关键条件

  1. 用户已登录受信任网站A:攻击依赖用户的活跃会话。
  2. 网站A未启用CSRF防护:如未校验 Token、Referer 或二次验证。
  3. 请求参数可预测:例如通过 GET 请求执行敏感操作(如 GET /转账?to=攻击者)。

防御措施(引用自网页5、网页6)

• Token 验证:在表单或请求头中嵌入随机 Token,服务端校验 Token 合法性。

• SameSite Cookie:设置 Cookie 的 SameSite=Strict/Lax 属性,限制跨域请求携带 Cookie。

• Referer 检查:验证请求来源是否为可信域名。


通过顺序图可以看出,CSRF 攻击的 核心逻辑是滥用浏览器的 Cookie 自动携带机制,而防御的关键在于 阻断攻击者伪造请求的能力。

Security的CSRF简介

根据 Spring Security 的官方设计理念及社区实践(综合多个技术文档和博客),其 CSRF 防护机制的核心逻辑如下:


一、Spring Security 的 CSRF 防护机制

  1. 默认启用的防护
    • 自动拦截:Spring Security 从 4.0 版本起默认启用 CSRF 保护,通过 CsrfFilter 拦截所有非安全 HTTP 方法(如 POST、PUT、DELETE)的请求。

• Token 验证流程:

  1. 生成 Token:用户首次访问时,服务端生成唯一的 CSRF Token 并存储于 HttpSessionCookie 中(默认使用 HttpSessionCsrfTokenRepository)。

  2. 客户端携带 Token:在表单或 AJAX 请求中必须包含该 Token(例如通过隐藏字段或请求头)。

  3. 服务端校验:请求到达时,CsrfFilter 会对比客户端提交的 Token 与服务端存储的 Token,若不一致则拒绝请求(返回 403 错误)。

  4. 核心组件

    CsrfToken 接口:定义 Token 的生成规则,包含 token 值、参数名(_csrf)和请求头名(X-CSRF-TOKEN)。

CsrfTokenRepository

HttpSessionCsrfTokenRepository(默认):Token 存储于 Session。

CookieCsrfTokenRepository:Token 存储于 Cookie,适用于前后端分离场景。

• 配置示例:

java 复制代码
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .csrf()
                .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
    }
}
  1. 前端集成方式
    • 表单页面:通过模板引擎(如 Thymeleaf)自动注入 Token:
html 复制代码
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>

• AJAX 请求:从 Cookie 或 Meta 标签获取 Token 并添加到请求头:

javascript 复制代码
// 从 Cookie 获取 Token(需配置 CookieCsrfTokenRepository)
const token = document.cookie.match(/XSRF-TOKEN=([^;]+)/)[1];
fetch('/api/data', {
    method: 'POST',
    headers: { 'X-XSRF-TOKEN': token }
});
  1. 扩展防护策略
    • SameSite Cookie 属性:通过设置 Cookie 的 SameSite=Strict/Lax,限制跨域请求携带 Cookie(需浏览器支持)。

• 二次验证:对敏感操作(如转账)叠加验证码或密码确认。


二、未启用 CSRF 防护的危害场景

如果未启用 CSRF 防护,攻击者可利用以下漏洞发起攻击:

  1. 伪造用户操作:

    • 自动触发恶意请求:通过恶意页面嵌入 <img> 或自动提交表单,诱导已登录用户触发转账、修改密码等操作。

    • 示例攻击代码:

    html 复制代码
    <img src="http://bank.com/transfer?to=attacker&amount=10000">
  2. 数据篡改与泄露:

    • 账户信息泄露:攻击者篡改用户邮箱或手机号,后续可通过"忘记密码"功能接管账户。

    • 业务逻辑绕过:例如自动关注陌生账号、删除用户数据等。

  3. 企业级风险:

    • 供应链攻击:通过管理员账户的 CSRF 漏洞植入后门,导致企业系统被渗透。

    • 合规风险:因数据泄露违反 GDPR 等法规,面临高额罚款。


三、官方文档的补充说明

虽然未直接引用 spring.io 官网,但以上机制与官方文档一致(可通过 Spring Security 官方文档 验证):

• 防护原理:基于 Token 的同步器模式(Synchronizer Token Pattern)。

• 禁用场景:仅推荐在纯 API 服务(无浏览器交互)时通过 http.csrf().disable() 关闭防护。


总结

Spring Security 通过 CSRF Token 的生成与验证机制 有效防御跨站请求伪造攻击。若未启用防护,攻击者可利用用户已登录的会话劫持敏感操作,导致数据泄露、资金损失等严重后果。开发者应结合业务场景选择 Token 存储方式(Session/Cookie),并确保前端正确集成 Token。

CSRF防范的必要参数

以下是标准的CSRF防护参数及其生成、使用和失效规则的总结表格,结合多个技术文档和实践案例:

参数名称 生成者 生成时机 使用时机 失效条件
CSRF Token 服务端 用户首次访问受保护页面时生成 在提交表单或发起状态变更请求(如POST/PUT/DELETE)时携带 会话过期失效、单次使用后失效(单次有效性)、超出时间窗口(如5-10分钟)
SameSite Cookie 服务端 用户首次登录时生成 浏览器自动管理,用于限制跨域请求携带Cookie Cookie过期失效、浏览器关闭(根据SameSite策略)
二次验证参数 服务端或第三方系统 用户触发敏感操作(如转账)时生成 执行关键操作前需二次验证(如短信验证码) 验证码使用后失效、超时失效(如5分钟)

详细说明

  1. CSRF Token
    • 生成者:服务端通过CsrfTokenRepository生成,例如HttpSessionCsrfTokenRepository(存储在会话中)或CookieCsrfTokenRepository(存储在Cookie)。

• 生成时机:用户首次访问需要CSRF防护的页面时(如登录页、表单页),或每次页面加载时动态生成新Token。

• 使用时机:必须嵌入到所有非安全方法(POST/PUT/DELETE)的请求中,例如:

• 表单:通过隐藏字段<input type="hidden" name="_csrf" value="token">

• AJAX:通过请求头X-CSRF-TOKENX-XSRF-TOKEN传递。

• 失效条件:

• 会话过期:若用户会话终止,Token随之失效。

• 单次有效性:部分系统设计Token仅限单次使用(如支付场景)。

• 时间窗口:设置Token有效期(如10分钟),超时自动失效。

  1. SameSite Cookie
    • 生成者:服务端在用户登录时生成会话Cookie,并设置SameSite属性。

• 使用规则:

SameSite=Strict:禁止跨域请求携带Cookie(适用于高敏感操作)。

SameSite=Lax:允许安全跨域请求(如导航链接的GET请求)。

• 失效条件:遵循Cookie的过期策略(如会话Cookie在浏览器关闭后失效)。

  1. 二次验证参数
    • 生成者:服务端在用户触发敏感操作时生成(如短信验证码、动态口令)。

• 使用时机:关键操作(如修改密码、大额转账)前需用户二次确认。

• 失效条件:验证码使用后立即失效,或设计为短时间有效(如5分钟)。


引用来源

• CSRF Token生成与验证逻辑:

• SameSite Cookie机制:

• 二次验证参数设计:

通过上述参数组合(如Token+SameSite+二次验证),可构建多层防御体系,有效阻断CSRF攻击。

Security是怎么防范的

Spring Security 通过 CSRF Token 验证机制 和 防御策略组合 来避免 CSRF 攻击,以下是其核心实现逻辑及关键步骤:


一、CSRF Token 验证机制

  1. 生成与存储 Token
    • Token 生成:当用户首次访问受保护页面时,Spring Security 会自动生成一个唯一的随机 CSRF Token。

• 默认使用 HttpSessionCsrfTokenRepository,将 Token 存储在用户会话(HttpSession)中。

• 若为前后端分离架构,可使用 CookieCsrfTokenRepository 将 Token 存储于 Cookie 中,并允许前端通过 JavaScript 读取。

• Token 结构:包含三个核心属性:token(随机值)、parameterName(参数名,默认为 _csrf)、headerName(请求头名,默认为 X-CSRF-TOKEN)。

  1. 客户端携带 Token
    • 表单提交:

在 HTML 表单中通过隐藏字段嵌入 Token。例如使用 Thymeleaf 模板引擎自动注入:

html 复制代码
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>

• AJAX 请求:

通过请求头传递 Token。前端需从 Cookie 或 Meta 标签中获取 Token,并添加到请求头中:

javascript 复制代码
// 从 Cookie 获取 Token(需配置 CookieCsrfTokenRepository)
const token = document.cookie.match(/XSRF-TOKEN=([^;]+)/)[1];
fetch('/api/data', {
    method: 'POST',
    headers: { 'X-XSRF-TOKEN': token }
});
  1. 服务端验证 Token
    • 拦截与校验:

CsrfFilter 会拦截所有非安全 HTTP 方法(如 POST、PUT、DELETE),从请求中提取 Token,并与服务端存储的 Token 对比。

• 若 Token 匹配,请求通过。

• 若 Token 缺失或不匹配,返回 403 Forbidden 错误。


二、防御策略扩展

  1. SameSite Cookie 属性
    • 通过设置 Cookie 的 SameSite 属性限制跨域请求携带 Cookie:

SameSite=Strict:仅允许同站点请求携带 Cookie。

SameSite=Lax:允许部分安全跨站点请求(如导航链接)。

• 配置示例:

java 复制代码
@Bean
public CsrfTokenRepository csrfTokenRepository() {
    CookieCsrfTokenRepository repository = new CookieCsrfTokenRepository();
    repository.setSameSite("Lax");
    return repository;
}
  1. 双重验证(Double Submit Cookie)
    • 服务端将 Token 同时存储在 Cookie 和表单/请求头中,验证时需两者一致。

• 适用于分布式系统,避免依赖会话存储。

  1. 安全方法限制
    • 默认仅对 POST、PUT、DELETE、PATCH 等状态修改类请求启用 CSRF 验证,而 GET、HEAD、OPTIONS 等安全方法无需验证。

三、配置与最佳实践

  1. 启用与禁用
    • 默认启用:Spring Security 4.0+ 默认开启 CSRF 防护。

• 手动关闭(不推荐):

java 复制代码
http.csrf().disable();
  1. 前后端分离配置
    • 后端配置 Cookie 存储 Token:
java 复制代码
http.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());

• 前端从 Cookie 读取 Token 并添加到请求头。

  1. 最佳实践
    • 始终启用 CSRF 防护:除非服务为纯 API 且无浏览器交互。

• 结合 HTTPS:防止 Token 被中间人窃取。

• 定期更新依赖:修复已知漏洞。


四、总结

Spring Security 通过 CSRF Token 的生成、传递与验证机制,结合 SameSite Cookie 和 双重验证 等策略,有效阻断攻击者伪造请求的能力。其设计兼顾灵活性与安全性,开发者需根据架构(如传统 MVC 或前后端分离)选择合适的 Token 存储方式,并遵循最佳实践以确保全面防护。

相关推荐
拾光拾趣录3 分钟前
CSS 深入解析:提升网页样式技巧与常见问题解决方案
前端·css
莫空00004 分钟前
深入理解JavaScript属性描述符:从数据属性到存取器属性
前端·面试
guojl4 分钟前
深度剖析Kafka读写机制
前端
FogLetter5 分钟前
图片懒加载:让网页飞起来的魔法技巧 ✨
前端·javascript·css
Mxuan6 分钟前
vscode webview 插件开发(精装篇)
前端
Mxuan7 分钟前
vscode webview 插件开发(交付篇)
前端
Mxuan8 分钟前
vscode 插件与 electron 应用跳转网页进行登录的实践
前端
拾光拾趣录8 分钟前
JavaScript 加载对浏览器渲染的影响
前端·javascript·浏览器
Codebee8 分钟前
OneCode图表配置速查手册
大数据·前端·数据可视化
然我9 分钟前
React 开发通关指南:用 HTML 的思维写 JS🚀🚀
前端·react.js·html