spring-boot-starter-parent:2.7.6
spring-cloud-alibaba-dependencies:2021.0.1.0
使用人人开源快速开发后台管理页面的时候产生了跨域问题,按照以往的经验,在gateway中添加配置类即可,但是在这次发现无效,最终还是产生了跨域问题。
@Configuration
public class CorsConfig {
@Bean
public CorsFilter corsFilter() {
final UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource();
final CorsConfiguration corsConfiguration = new CorsConfiguration();
/*是否允许请求带有验证信息*/
corsConfiguration.setAllowCredentials(true);
/*允许访问的客户端域名*/
corsConfiguration.addAllowedOrigin("*");
/*corsConfiguration.addAllowedOriginPattern("*");*/
/*允许服务端访问的客户端请求头*/
corsConfiguration.addAllowedHeader("*");
/*允许访问的方法名,GET POST等*/
corsConfiguration.addAllowedMethod("*");
urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration);
return new CorsFilter(urlBasedCorsConfigurationSource);
}
}
明明以前使用这个配置类的时候是没有问题的,是可以解决跨域问题的,但是这次同样的操作却失败了,之后再网上找了很久,各种解决跨域的方法都试过了
WebMvcConfigurer需要导入web包,gateway使用的webflux,GG
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Bean
public WebMvcConfigurer corsConfigurer()
{
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").
allowedOrigins("*").
allowedMethods("*"). //允许任何方法(post、get等)
allowedHeaders("*"). //允许任何请求头
allowCredentials(true). //带上cookie信息
exposedHeaders(HttpHeaders.SET_COOKIE).maxAge(3600L); //maxAge(3600)
}
};
}
}
原文
有人说是因为过滤器的执行顺序的问题,比如jwt过滤器在CorsFilter前面,所以在进行跨域处理之前,OPTIONS请求就被拒绝了,因为还不知道具体要怎么调试来查看一个请求在gateway的处理方式,所以我的问题到底是不是这个原因还不知道,而且最终这个方法不适合我,GG
产生的问题:
javax.servlet
servlet-api
2.5
@Configuration
public class CorsConfig {
@Bean
public FilterRegistrationBean corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
// 使用setAllowedOrigin会出现IllegalArgumentException
config.addAllowedOriginPattern("*");
config.addAllowedHeader("*");
config.addAllowedMethod("*");
source.registerCorsConfiguration("/**", config);
FilterRegistrationBean<CorsFilter> bean = new FilterRegistrationBean<CorsFilter>(new CorsFilter(source));
//设置优先级
bean.setOrder(0);
return bean;
}
}
原文
后来在网上找到了有关gateway的跨域解决,虽然解决了跨域问题,但是很不幸,产生了双重跨域问题,但是其他地方并没有处理跨域,不知道是什么情况
之前使用nginx的时候也产生过类似的问题,使用oss的时候也会这样,只要携带了图片信息就会产生跨域问题,明明之前的所有服务都可以正常运行,网上说要设置nginx的运行传输内容大小,但是还是没用,最终nginx的问题也没有解决
不过至少跨域问题解决了,就是不知道哪里出现了双重跨域
@Configuration
public class GlobalCorsConfig {
@Bean
public WebFilter corsFilter() {
return (ServerWebExchange ctx, WebFilterChain chain) -> {
ServerHttpRequest request = ctx.getRequest();
if (CorsUtils.isCorsRequest(request)) {
HttpHeaders requestHeaders = request.getHeaders();
ServerHttpResponse response = ctx.getResponse();
HttpMethod requestMethod = requestHeaders.getAccessControlRequestMethod();
HttpHeaders headers = response.getHeaders();
headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, requestHeaders.getOrigin());
headers.addAll(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS,
requestHeaders.getAccessControlRequestHeaders());
if (requestMethod != null) {
headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS, requestMethod.name());
}
headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true");
headers.add(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS, "*");
if (request.getMethod() == HttpMethod.OPTIONS) {
response.setStatusCode(HttpStatus.OK);
return Mono.empty();
}
}
return chain.filter(ctx);
};
}
}
原文
后来又发现了一个新奇的东西,通过在gateway中的配置文件解决跨域,但是还是没有用
spring:
cloud:
gateway:
# gateway的全局跨域请求配置
globalcors:
corsConfigurations:
'[/**]':
allowedHeaders: "*"
allowedOrigins: "*"
allowCredentials: true
allowedMethods: "*"
后来发现了该作者本身也出现了双重跨域问题,解决方法就是去除重复的请求头
spring:
cloud:
gateway:
default-filters:
- DedupeResponseHeader=Access-Control-Allow-Origin Access-Control-Allow-Credentials Vary, RETAIN_UNIQUE
还没搞懂这是为什么,也许是版本问题?
最终使用了两个方案的结合体,勉强解决了问题
在gateway中创建配置类,虽然解决了跨域问题,但是产生了双重跨域
@Configuration
public class GlobalCorsConfig {
@Bean
public WebFilter corsFilter() {
return (ServerWebExchange ctx, WebFilterChain chain) -> {
ServerHttpRequest request = ctx.getRequest();
if (CorsUtils.isCorsRequest(request)) {
HttpHeaders requestHeaders = request.getHeaders();
ServerHttpResponse response = ctx.getResponse();
HttpMethod requestMethod = requestHeaders.getAccessControlRequestMethod();
HttpHeaders headers = response.getHeaders();
headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, requestHeaders.getOrigin());
headers.addAll(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS,
requestHeaders.getAccessControlRequestHeaders());
if (requestMethod != null) {
headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS, requestMethod.name());
}
headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true");
headers.add(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS, "*");
if (request.getMethod() == HttpMethod.OPTIONS) {
response.setStatusCode(HttpStatus.OK);
return Mono.empty();
}
}
return chain.filter(ctx);
};
}
}
在gateway中使用配置文件剔除重复响应头信息,解决双重跨域
spring:
cloud:
gateway:
default-filters:
- DedupeResponseHeader=Access-Control-Allow-Origin Access-Control-Allow-Credentials Vary, RETAIN_UNIQUE
完成这两个修改后,至少我是解决了我的跨域问题