首页 > 其他分享 >Spring Security 防止 CSRF 攻击

Spring Security 防止 CSRF 攻击

时间:2024-11-11 15:32:12浏览次数:1  
标签:csrf Spring 36 filter CSRF import Security httpSecurity

使用 security 是 3.3.2 版本

1、 启用 CSRF ,security 自带功能

 1   @Bean
 2     public SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
 3         // 禁用默认的登录和退出
 4         httpSecurity.formLogin(AbstractHttpConfigurer::disable);
 5         httpSecurity.logout(AbstractHttpConfigurer::disable);
 6         //开启 CSRF
 7         httpSecurity.csrf(csrf -> csrf
 8                 .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()));
 9         httpSecurity.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS));
10         // 配置拦截规则
11         httpSecurity.authorizeHttpRequests(authorizeHttpRequests -> authorizeHttpRequests
12             // 放行白名单
13             .requestMatchers(CollUtil.isEmpty(ignoreWhiteProperties.getWhites()) ? new String[0] :
14                 ignoreWhiteProperties.getWhites().toArray(new String[0])).permitAll()
15             // 需要鉴权认证
16             .anyRequest().authenticated());
17 
18         // 添加过滤器
19         httpSecurity.addFilterBefore(authTokenFilter(), UsernamePasswordAuthenticationFilter.class);
20 
21         // 异常时认证处理流程
22         httpSecurity.exceptionHandling(
23             exceptionHandlingConfigurer -> exceptionHandlingConfigurer.authenticationEntryPoint(
24                 authenticationEntryPoint()).accessDeniedHandler(accessDeniedHandler()));
25         return httpSecurity.build();
26     }

 

2、 spring gateway  中添加过滤器先进行添加36位 空字符,再进行 base64 编码,重新写入请求头中

 1 package com.changan.gateway.filter;
 2 
 3 import org.springframework.cloud.gateway.filter.GatewayFilterChain;
 4 import org.springframework.cloud.gateway.filter.GlobalFilter;
 5 import org.springframework.stereotype.Component;
 6 import org.springframework.web.server.ServerWebExchange;
 7 import reactor.core.publisher.Mono;
 8 
 9 import java.nio.charset.StandardCharsets;
10 import java.util.Base64;
11 
12 /**
13  * CSRF 在头信息中额外生成36个空字符,使其校验通过
14  */
15 @Component
16 public class CsrfGlobalFilter implements GlobalFilter {
17 
18     private final StringBuffer preHead = new StringBuffer();
19 
20     public CsrfGlobalFilter(){
21         // 生成36位随机数
22         preHead.append("\u0000".repeat(36));
23     }
24 
25     @Override
26     public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
27         //获取前端传递的 X-Xsrf-Token 头信息
28         String headerValue = exchange.getRequest().getHeaders().getFirst("X-Xsrf-Token");
29         //在 X-Xsrf-Token 头信息之前添加 36 位空字符
30         headerValue = preHead + headerValue;
31         //base64 加密
32         String encodedValue = Base64.getEncoder().encodeToString(headerValue.getBytes(StandardCharsets.UTF_8));
33 
34         exchange.getRequest().mutate()
35                 .header("X-Xsrf-Token", encodedValue)
36                 .build();
37 
38         return chain.filter(exchange);
39     }
40 
41 }

 

总结:

  Security 自带 CSRF 功能,他会在第一次 POST 请求后会在 cookie 中存储一个 csrf_token 值,前端有的框架会自动识别,下次请求会自动携带上,就可以防止 CSRF 攻击

 

注意:

  按常理是这样的,可是 3.3.2 版本跟进源码发现,需要有一个 36 位 前缀随机数,但是后续需要异或运算= csrf_token 本身才放行。这里应该是要通过计算得出。
  上述为了能实现功能,暂时直接用 “空字符” 也能成功

 

标签:csrf,Spring,36,filter,CSRF,import,Security,httpSecurity
From: https://www.cnblogs.com/hylr/p/18539798

相关文章