Spring 5.3+ CorsConfiguration抛出IllegalArgumentException总结

更新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 when allowCredentials is true, allowedOrigins does not 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;
	}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值