更新
Spring5.3+
或者SpringBoot 2.4.0+
时,CorsConfiguration.validateAllowCredentials()
可能抛出
IllegalArgumentException
(
"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.”)
解决方法
方法调用
你调用的方法需要做出以下修改
CorsConfiguration.addAllowedOrigin(); -------------> CorsConfiguration.addAllowedOriginPattern();
CorsConfiguration.setAllowedOrigins(); -------------> CorsConfiguration.setAllowedOriginPatterns();
@CrossOrigin
注解
@CrossOrigin(originPatterns = {"*"}) //添加originPatterns属性
细节分析
CorsConfiguration.validateAllowCredentials()
是抛出异常的方法
Validate that whenallowCredentials
istrue
,allowedOrigins
doesnot
contain the special value “*” since in that case the"Access-Control-Allow-Origin"
cannot be set to “*”.
public void validateAllowCredentials() {
//如果allowCredentials为true,allowedOrigins不为null且包含*则抛出异常
if (this.allowCredentials == Boolean.TRUE &&
this.allowedOrigins != null && this.allowedOrigins.contains(ALL)) {
throw new IllegalArgumentException(
"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.");
}
}
@CrossOrigin
引发抛出异常细节如下:
AbstractHandlerMethodMapping.MappingRegistry#register()
此方法用于注册HandlerMethod,每一个HandlerMethod都会执行这个方法,而此方法内调用了initCorsConfiguration()
.
public void register(T mapping, Object handler, Method method) {
//-----省略
CorsConfiguration corsConfig = initCorsConfiguration(handler, method, mapping);//初始化corsConfig
if (corsConfig != null) {
corsConfig.validateAllowCredentials();
this.corsLookup.put(handlerMethod, corsConfig);
}
//-----省略
protected CorsConfiguration initCorsConfiguration(Object handler, Method method, RequestMappingInfo mappingInfo) {
HandlerMethod handlerMethod = createHandlerMethod(handler, method);
Class<?> beanType = handlerMethod.getBeanType();
//判断Controller上有无@CrossOrigin注解
CrossOrigin typeAnnotation = AnnotatedElementUtils.findMergedAnnotation(beanType, CrossOrigin.class);
//判断方法上有无@CrossOrigin注解
CrossOrigin methodAnnotation = AnnotatedElementUtils.findMergedAnnotation(method, CrossOrigin.class);
//有@CrossOrigin注解则继续执行,没有返回null
if (typeAnnotation == null && methodAnnotation == null) {
return null;
}
CorsConfiguration config = new CorsConfiguration();
updateCorsConfig(config, typeAnnotation);
updateCorsConfig(config, methodAnnotation);
if (CollectionUtils.isEmpty(config.getAllowedMethods())) {
for (RequestMethod allowedMethod : mappingInfo.getMethodsCondition().getMethods()) {
config.addAllowedMethod(allowedMethod.name());
}
}
return config.applyPermitDefaultValues();//返回前调用的方法设置了config的默认值
}
applyPermitDefaultValues()
此方法决定了返回的CorsConfiguration属性的默认值,解释了为什么validateAllowCredentials()
会抛出异常
public CorsConfiguration applyPermitDefaultValues() {
//若allowedOrigins和allowedOriginPatterns都为null, 则设置allowedOrigins为 *
if (this.allowedOrigins == null && this.allowedOriginPatterns == null) {
this.allowedOrigins = DEFAULT_PERMIT_ALL;
}
if (this.allowedMethods == null) {
this.allowedMethods = DEFAULT_PERMIT_METHODS;
this.resolvedMethods = DEFAULT_PERMIT_METHODS
.stream().map(HttpMethod::resolve).collect(Collectors.toList());
}
if (this.allowedHeaders == null) {
this.allowedHeaders = DEFAULT_PERMIT_ALL;
}
if (this.maxAge == null) {
this.maxAge = 1800L;
}
return this;
}