Spring Security环境下CORS跨域失效问题
前后端分离项目中,后端已经配置对跨域支持,前端还是报请求跨域问题。
基于Spring MVC正常配置跨域问题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| @Configuration public class WebMvcConfig extends WebMvcConfigurerAdapter {
private CorsConfiguration buildConfig() { CorsConfiguration corsConfiguration = new CorsConfiguration(); corsConfiguration.addAllowedOrigin("*"); corsConfiguration.addAllowedHeader("*"); corsConfiguration.addAllowedMethod("*"); corsConfiguration.addExposedHeader("Authorization"); return corsConfiguration; }
@Bean public CorsFilter corsFilter() { UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", buildConfig()); return new CorsFilter(source); }
@Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("*") .allowedMethods("POST", "GET", "PUT", "OPTIONS", "DELETE") .allowedHeaders("*") .maxAge(3600) .allowCredentials(true); }
}
|
配置完成后前端控制他还是显示请求跨域问题,说明上面的配置失效了。
跨域失效原因
启动 spring boot 项目,观察控制台打印的过滤器 chain 的顺序 cors filter 是在 spring security filter chain 之后。
1 2 3 4 5 6 7
| o.s.b.w.s.FilterRegistrationBean - Mapping filter: 'characterEncodingFilter' to: [/*] o.s.b.w.s.FilterRegistrationBean - Mapping filter: 'hiddenHttpMethodFilter' to: [/*] o.s.b.w.s.FilterRegistrationBean - Mapping filter: 'httpPutFormContentFilter' to: [/*] o.s.b.w.s.FilterRegistrationBean - Mapping filter: 'requestContextFilter' to: [/*] o.s.b.w.s.DelegatingFilterProxyRegistrationBean - Mapping filter: 'springSecurityFilterChain' to: [/*] o.s.b.w.s.FilterRegistrationBean - Mapping filter: 'corsFilter' to: [/*] o.s.b.w.s.ServletRegistrationBean - Servlet dispatcherServlet mapped to [/]
|
所以,问题很清晰了,问题在于 spring security 的 过滤器链,我们只需要将手动创建的跨域 filter 置于 spring security filter chain 之前即可。
解决
- 在Spring Security配置文件中configure方法开启跨域
1 2 3 4 5 6 7 8
| @Override public void configure(HttpSecurity http) throws Exception { http .cors(). and() .authorizeRequests() …… }
|
- 手动实现跨域过滤器并将过滤器置于spring security filter chain之前
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
public class WebSecurityCorsFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletResponse res = (HttpServletResponse) response; res.setHeader("Access-Control-Allow-Origin", "*"); res.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT"); res.setHeader("Access-Control-Max-Age", "3600"); res.setHeader("Access-Control-Allow-Headers", "Authorization, Content-Type, Accept, x-requested-with, Cache-Control"); chain.doFilter(request, res); } @Override public void destroy() { } }
|
1
| .and().addFilterBefore(new WebSecurityCorsFilter(), ChannelProcessingFilter.class)
|