1.SpringBoot跨域设置 主要有四种方式:
方式1:返回新的CorsFilter;
方式2:重写WebMvcConfigurer;
方式3:使用注解(@CrossOrigin)
方式4:手工设置响应头(HttpServletResponse )。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 @Configuration @ControllerAdvice public class MvcConfig implements WebMvcConfigurer { @Override public void addCorsMappings (CorsRegistry registry) { registry.addMapping("/**" ) .allowedOrigins("*" ) .allowCredentials(true ) .allowedMethods("GET" ,"POST" , "PUT" , "DELETE" ) .allowedHeaders("*" ); } }
这种方式的缺点是,假如spring boot配置了拦截器(为了实现权限验证),假如用户身份不通过,拦截器方法preHandle一般会返回false,阻止拦截器继续执行,但也同时把上面设置的处理跨域的拦截器禁止掉,自然也就完成不了拦截器。解决方式是下面这种方式。如果重写WebMvcConfigurer,Idea会出现这个问题“No interface expected here”。
问题出在要使用implements,而不是 extends。
参考文章: 1.SpringBoot—-跨域配置 2.springboot 解决跨域 3.Spring Security的WebMvcConfigurerAdapter已过时 4.WebMvcConfigurerAdapter已过时 (这里解决WebMvcConfigurerAdapter过时问题) 5.SpringBoot配置Cors解决跨域请求问题 6.[Spring Boot配置接口 WebMvcConfigurer}(https://blog.csdn.net/fmwind/article/details/81235401 ) 7.Spring Boot 2.4.5 跨域解决 这篇文章解决了问题 8.springboot 跨域处理无效填坑篇 第一种 @CrossOrigin,第二种 WebMvcConfigurer 都失败了,使用了 CorsFilter实现Filter,验证成功 9.SpringBoot配置CORS解决跨域时的坑 这个也是用了CorsFilter实现的,但是我遇到的问题是 UrlBasedCorsConfigurationSource无法转换为org.springframework.web.cors.CorsConfigurationSource
3.自定义filter 通过定义自己的filter,代替原先的拦截器。一个http请求,先走filter,到达servlet后才进行拦截器的处理,如果我们把cors放在filter里,就可以优先于权限拦截器执行。代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 @Configuration public class CorsConfig { @Bean public CorsFilter corsFilter () { CorsConfiguration config = new CorsConfiguration (); config.addAllowedOriginPattern("*" ); config.setAllowCredentials(true ); config.addAllowedMethod("*" ); config.addAllowedHeader("*" ); UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource (); configSource.registerCorsConfiguration("/**" , config); return new CorsFilter (configSource); } }
这里要注意的是CorsFilter,引入的包是org.springframework.web.filter.CorsFilter,而不是apache那个。
4.自定义FilterRegistrationBean 这种和第二种也是类似的,行不行,没实验。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 @Configuration public class CorsConfig { @Bean public FilterRegistrationBean corsFilter () { UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource (); CorsConfiguration config = new CorsConfiguration (); config.setAllowCredentials(true ); config.addAllowedOrigin("http://localhost:4200" ); config.addAllowedHeader("*" ); config.addAllowedMethod("*" ); source.registerCorsConfiguration("/**" , config); FilterRegistrationBean bean = new FilterRegistrationBean (new CorsFilter (source)); bean.setOrder(0 ); return bean; } }
5.扩展OncePerRequestFilter 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 31 32 33 34 public class CorsFilter extends OncePerRequestFilter { static final String ORIGIN = "Origin" ; protected void doFilterInternal ( HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { String origin = request.getHeader(ORIGIN); response.setHeader("Access-Control-Allow-Origin" , "*" ); response.setHeader("Access-Control-Allow-Credentials" , "true" ); response.setHeader("Access-Control-Allow-Methods" , "PUT, POST, GET, OPTIONS, DELETE" ); response.setHeader("Access-Control-Max-Age" , "3600" ); response.setHeader("Access-Control-Allow-Headers" , "content-type, authorization" ); if (request.getMethod().equals("OPTIONS" )) response.setStatus(HttpServletResponse.SC_OK); else filterChain.doFilter(request, response); } } @Bean public CorsFilter corsFilter () throws Exception { return new CorsFilter (); } http .addFilterBefore(corsFilter(), UsernamePasswordAuthenticationFilter.class) .addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class) .headers() .cacheControl();
参考文档: 1.SpringMVC的Interceptor和Cors冲突 2.springboot设置cors跨域请求的两种方式 3.为什么出现OPTIONS?SpringBoot接口跨域解决方案 原来浏览器会在发送真正请求之前,先发送一个方法为OPTIONS的预检请求 Preflighted requests 这个请求是用来验证本次请求是否安全的,而且并不是所有请求都会发送,需要符合以下条件:1.请求方法不是GET/HEAD/POST。2.POST请求的Content-Type并非application/x-www-form-urlencoded, multipart/form-data, 或text/plain。3.请求设置了自定义的header字段
问题 (1) allowedOrigins cannot contain the special value ““ 在设置 allowCredentials的时候,出现了这个错误:When allowCredentials is true, allowedOrigins cannot contain the special value “ “ since that cannot be set on the “Access-Control-Allow-Origin” response header. To allow credentials to a set of origins, list them explicitly or consider using “allowedOriginPatterns” instead.
1 2 3 4 5 6 7 8 9 10 @Configuration public class CorsConfig { @Bean public CorsFilter corsFilter () { CorsConfiguration config = new CorsConfiguration (); config.addAllowedOrigin("*" ); config.setAllowCredentials(true ); } }
【解决方法】 将 addAllowedOrigin 改为 addAllowedOriginPattern;
1 2 3 4 5 6 7 8 9 10 11 @Configuration public class CorsConfig { @Bean public CorsFilter corsFilter () { CorsConfiguration config = new CorsConfiguration (); config.addAllowedOriginPattern("*" ); config.setAllowCredentials(true ); } }
参考文章: 1.Springboot跨域配置报错:When allowCredentials is true, allowedOrigins cannot contain the specia 使用 allowedOriginPatterns 替代,这个不行 2.gateway 报错 allowedOrigins cannot contain the special value 这个的gateway也是这么配置的