---
#### **一、CSRF攻击原理与危害**
**CSRF(跨站请求伪造)** 是一种利用用户已认证身份发起恶意请求的攻击方式。攻击者诱导用户访问恶意页面,该页面携带伪造请求(如转账、修改密码)发送至目标网站,由于浏览器自动携带用户的认证Cookie,服务端可能误认为是合法操作。  
**典型攻击流程**:  
1. 用户登录信任网站A,获取会话Cookie;  
2. 用户访问恶意网站B,触发对网站A的请求(如隐藏表单或图片);  
3. 浏览器自动携带Cookie,请求被网站A视为合法操作。  
**防御核心**:验证请求是否来自合法源,并携带可信凭证(如CSRF Token)。
---
#### **二、Spring Security的CSRF防护机制**
Spring Security通过 **令牌验证** 和 **安全属性配置** 实现CSRF防护,核心组件包括`CsrfToken`、`CsrfTokenRepository`和`CsrfFilter`。
##### **1. CSRF Token的生成与验证**
• **生成规则**:服务端为每个会话生成唯一随机Token(如UUID),存储于Session或Cookie中。  
• **存储方式**:  
  • **Session存储**:默认使用`HttpSessionCsrfTokenRepository`,Token与用户会话绑定。  
  • **Cookie存储**:通过`CookieCsrfTokenRepository`写入客户端,需设置`SameSite`和`Secure`属性增强安全性。  
• **验证流程**:  
  客户端提交请求时需携带Token(表单参数或请求头),服务端比对请求中的Token与存储值,不一致则拒绝请求。
**配置示例**:  
```java
@Configuration
@EnableWebSecurity
public class SecurityConfig {
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .csrf(c -> c.csrfTokenRepository(cookieCsrfTokenRepository()))
            .sessionManagement(s -> s.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED));
        return http.build();
    }
    private CsrfTokenRepository cookieCsrfTokenRepository() {
        CookieCsrfTokenRepository repo = CookieCsrfTokenRepository.withHttpOnlyFalse();
        repo.setCookieDomain("example.com");
        repo.setSameSite("Lax");  // 支持跨站安全请求
        return repo;
    }
}
```
##### **2. SameSite属性增强防御**
• **作用**:限制Cookie的跨站传递,防止恶意站点利用用户Cookie发起请求。  
  • `SameSite=Strict`:完全禁止跨站携带Cookie,适用于敏感操作(如支付)。  
  • `SameSite=Lax`:允许安全的跨站请求(如导航类GET请求),平衡安全性与用户体验。  
• **配置**:  
  ```java
  ResponseCookie cookie = ResponseCookie.from("XSRF-TOKEN", token)
      .sameSite("Lax")
      .secure(true)
      .httpOnly(true)
      .build();
  ```
##### **3. CsrfFilter的工作机制**
`CsrfFilter`是Spring Security处理CSRF的核心过滤器,其流程如下:  
1. **Token加载**:从`CsrfTokenRepository`加载当前会话的Token,若不存在则生成并存储。  
2. **请求放行**:对安全方法(GET、HEAD等)直接放行,不验证Token。  
3. **Token校验**:对非安全方法(POST、PUT等),检查请求参数或头中的Token是否匹配,否则返回403。  
**源码关键逻辑**:  
```java
public class CsrfFilter extends OncePerRequestFilter {
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) {
        CsrfToken csrfToken = tokenRepository.loadToken(request);
        if (csrfToken == null) {
            csrfToken = tokenRepository.generateToken(request);
            tokenRepository.saveToken(csrfToken, request, response);
        }
        request.setAttribute(CsrfToken.class.getName(), csrfToken);
        if (!requiresCsrfProtection(request)) {
            chain.doFilter(request, response);
            return;
        }
        String actualToken = request.getHeader(csrfToken.getHeaderName());
        if (actualToken == null) {
            actualToken = request.getParameter(csrfToken.getParameterName());
        }
        if (!csrfToken.getToken().equals(actualToken)) {
            response.sendError(HttpStatus.FORBIDDEN.value());
            return;
        }
        chain.doFilter(request, response);
    }
}
```
---
#### **三、分布式场景下的CSRF防护:Spring Session与Redis集成**
在微服务架构中,会话数据需跨服务共享,传统Session存储无法满足需求。**Spring Session** 通过将会话数据存储到Redis,实现分布式一致性。
##### **1. 集成Spring Session与Redis**
• **依赖引入**:  
  ```xml
  <dependency>
      <groupId>org.springframework.session</groupId>
      <artifactId>spring-session-data-redis</artifactId>
  </dependency>
  <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-redis</artifactId>
  </dependency>
  ```
• **配置Redis连接**:  
  ```yaml
  spring:
    redis:
      host: localhost
      port: 6379
    session:
      store-type: redis
  ```
• **启用Redis存储**:  
  ```java
  @Configuration
  @EnableRedisHttpSession
  public class SessionConfig {
      @Bean
      public LettuceConnectionFactory redisConnectionFactory() {
          return new LettuceConnectionFactory();
      }
  }
  ```
##### **2. CSRF Token的分布式存储**
• **自动同步**:使用`HttpSessionCsrfTokenRepository`时,Token随Session自动存入Redis,各服务节点通过Session ID读取验证。  
• **性能优化**:设置合理的TTL(如30分钟),避免Redis存储膨胀。
---
#### **四、最佳实践与安全增强建议**
1. **分层防御策略**:  
   • 敏感操作启用`SameSite=Strict`和二次验证(如短信验证码)。  
   • 非敏感操作使用`SameSite=Lax`,兼顾安全与体验。  
2. **HTTPS强制**:所有涉及Cookie和Token的通信启用HTTPS,防止中间人攻击。  
3. **监控与审计**:记录CSRF验证失败的请求,分析潜在攻击行为。  
4. **兼容性处理**:对不支持SameSite的旧浏览器,回退至Token验证为主。
---
#### **五、总结**
Spring Security通过 **CSRF Token验证**、**SameSite属性** 和 **分布式会话管理** 构建了多层次的防护体系。开发者需根据业务场景灵活选择存储方式(Session/Cookie)、配置安全属性,并结合Spring Session实现高可用架构。防御CSRF不仅是技术问题,更需在架构设计、监控响应等环节形成闭环,持续提升应用安全性。
**参考资料**:
					
					
					
				- 请尽量让自己的回复能够对别人有帮助
- 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
- 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
- 图片支持拖拽、截图粘贴等方式上传

 
							