如何在跨域调用中绕过security自带的csrf防御机制

笔者最近碰到了一种需要针对某一域名跳过spring security csrf防御机制的问题,网上找了好久也没找到可行的办法,最后还是笔者自己针对细节的检查,找到了破局的办法,下面介绍一下具体的原理和实现方法


一、绕过csrf防御机制的原理

原理主要就是通过security自带的csrf可以配置对一些特定的uri不进行拦截,而这种配置可以使用/**进行对uri模糊匹配,这样就可以在特定域名的服务中给所有请求当前服务的uri加上一个特定的前缀,然后在当前服务的过滤器中对特定前缀的uri进行转发,将其转发到正确的uri上,就能绕过security自带的csrf拦截机制了。

二、具体实现

跨域调用的请求配置

//伪代码--主要是展示给uri添加前缀
HttpUtil.post(host + "/muyichen" + requestURI);

服务端csrf拦截白名单配置

// 该方法是继承自WebSecurityConfigurerAdapter类
@Override
 protected void configure(HttpSecurity http) throws Exception {
    
    
     // 开启csrf白名单配置
     http.cors().and()
     			// 白名单
     			.csrf().ignoringAntMatchers("/muyichen/**");
 }

过滤器中的转发方法

@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    
    
	HttpServletRequest request = (HttpServletRequest) servletRequest;
	String requestURI = request.getRequestURI();
	String suffix = "/muyichen";
	// 如果前缀是/muyichen,表明该请求为跨域请求,需要转发到正确的地址
	if(suffix.equals(requestURI.substring(0, suffix.length()))) {
    
    
	    requestURI = requestURI.substring(suffix.length());
	    request.getRequestDispatcher(requestURI).forward(servletRequest, servletResponse);
	    return;
	}
	// 如果不是则跳过该过滤器
	filterChain.doFilter(servletRequest, servletResponse);
}

三、需要注意的地方

  • 1、转发过滤器最好是最后一个执行(如果没有特别配置的话,过滤器的执行顺序是按照首字母大小来排序的),因为这样不会影响之前的过滤逻辑(转发后请求不会再走过滤链了);
  • 2、使用这个方法后,Controller头部中配置的action前缀需要注意不要和过滤器中的前缀相同,如果相同的话当前控制器中的所有接口都不会走csrf校验;

猜你喜欢

转载自blog.csdn.net/qq_42697271/article/details/117287346