SpringSecurity 使用自定义过滤器解决跨域问题
因为跨域的请求,对于浏览器来说是复杂请求,所以会先发送一个 OPTIONS 类型的 HTTP 请求,这个请求不会携带任何信息,它的作用就是为了试探服务端是否能正常处理后续请求。
所以当 OPTIONS 请求进来,我们需要在响应头中告诉浏览器可以发送后续请求。
跨域的解决方案有很多,这里介绍的是利用过滤器来解决。
我们知道 spring security 的本质就是一个过滤器链。所以我们只需要在第一个过滤器之前加入我们自定义的过滤器来处理跨域信息即可。
public class AccessFilter extends GenericFilterBean {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) servletResponse;
HttpServletRequest request = (HttpServletRequest) servletRequest;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Encoding", "identity");
// 响应类型
response.setHeader("Access-Control-Allow-Methods", "*");
// 请求头添加了 token 字段,所以需要让其能通过
response.setHeader("Access-Control-Allow-Headers",
"Origin, X-Requested-With, Content-Type, Accept, Authorization, token");
response.setContentType("application/json; charset=utf-8");
response.setCharacterEncoding("utf-8");
// 探针请求,直接返回,无需执行后续过滤器。
if (request.getMethod().equals("OPTIONS"))
return;
filterChain.doFilter(request, response);
}
}
配置也很简单,只需要将这个过滤器放在过滤器链的第一个位置就行。
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
// 将 跨域过滤器放在第一个过滤器的位置
.addFilterBefore(new AccessFilter(), WebAsyncManagerIntegrationFilter.class)
}
}