在 CORS spring security + webFlux 中启用通配符
Enable wildcard in CORS spring security + webFlux
我在使用 spring webFlux 制作的项目中启用了 spring 安全 + CORS。我的问题是我们接受来自以下方面的请求:http://localhost:4200. How I can make that CORS will accept reqs from http://*.localhost:4200 like http://a.localhost:4200, http://b.localhost:4200 ?
我的 CORS 配置如下:
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public CorsWebFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.setAllowedOrigins(corsConfigData.getAllowedOrigins());
config.setAllowedHeaders(corsConfigData.getAllowedHeaders());
config.setAllowedMethods(corsConfigData.getAllowedMethods());
source.registerCorsConfiguration("/**", config);
return new CorsWebFilter(source);
}
你有什么想法吗???
我认为,如responses to this question, the CORS specification doesn't allow for wildcarding a subdomain. Specifically see https://www.w3.org/TR/cors/#access-control-allow-origin-response-header
所示
您可以按照他们对该答案的建议,将处理转移到某些中间件层,例如 NGINX 或 Apache,它们可以根据请求中的域动态设置 CORS header,或指定所有子域你会想要在 spring 引导配置中,如果这不是一个无法控制的数量的话。
尽管在问题的第一部分中您声明您接受来自 http://localhost:4200.
的请求,但如果您不需要子域,那么这应该不是问题,那么您可以明确地将那个域列入白名单,还是我理解错了?
我想我找到了一个可行的解决方案。这只是意味着创建一个自定义 CorsConfiguration,覆盖 checkOrigin 方法并创建一个将正确解释 http://*.localhost:4200 的自定义匹配器。代码如下所示:
public class RegexCorsConfiguration extends CorsConfiguration {
private List<String> allowedOriginsRegexes = new ArrayList<>();
/**
* Check the origin of the request against the configured allowed origins.
* @param requestOrigin the origin to check
* @return the origin to use for the response, possibly {@code null} which
* means the request origin is not allowed
*/
public String checkOrigin(String requestOrigin) {
if (!StringUtils.hasText(requestOrigin)) {
return null;
}
if (this.allowedOriginsRegexes.isEmpty()) {
return null;
}
if (this.allowedOriginsRegexes.contains(ALL)) {
if (getAllowCredentials() != Boolean.TRUE) {
return ALL;
} else {
return requestOrigin;
}
}
for (String allowedOriginRegex : this.allowedOriginsRegexes) {
if (createMatcher(requestOrigin, allowedOriginRegex).matches()) {
return requestOrigin;
}
}
return null;
}
public void setAllowedOriginRegex(List<String> allowedOriginsRegexes) {
this.allowedOriginsRegexes = allowedOriginsRegexes;
}
private Matcher createMatcher(String origin, String allowedOrigin) {
String regex = this.parseAllowedWildcardOriginToRegex(allowedOrigin);
Pattern pattern = Pattern.compile(regex);
return pattern.matcher(origin);
}
private String parseAllowedWildcardOriginToRegex(String allowedOrigin) {
String regex = allowedOrigin.replace(".", "\.");
return regex.replace("*", ".*");
}}
当然,从配置 类 中注入 corsConfig,如下所示:
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public CorsWebFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
RegexCorsConfiguration regexCorsConfiguration = new RegexCorsConfiguration();
regexCorsConfiguration.setAllowCredentials(true);
regexCorsConfiguration.setAllowedOriginRegex(corsConfigData.getAllowedOrigins());
regexCorsConfiguration.setAllowedHeaders(corsConfigData.getAllowedHeaders());
regexCorsConfiguration.setAllowedMethods(corsConfigData.getAllowedMethods());
source.registerCorsConfiguration("/**", regexCorsConfiguration);
return new CorsWebFilter(source);
}
我在使用 spring webFlux 制作的项目中启用了 spring 安全 + CORS。我的问题是我们接受来自以下方面的请求:http://localhost:4200. How I can make that CORS will accept reqs from http://*.localhost:4200 like http://a.localhost:4200, http://b.localhost:4200 ?
我的 CORS 配置如下:
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public CorsWebFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.setAllowedOrigins(corsConfigData.getAllowedOrigins());
config.setAllowedHeaders(corsConfigData.getAllowedHeaders());
config.setAllowedMethods(corsConfigData.getAllowedMethods());
source.registerCorsConfiguration("/**", config);
return new CorsWebFilter(source);
}
你有什么想法吗???
我认为,如responses to this question, the CORS specification doesn't allow for wildcarding a subdomain. Specifically see https://www.w3.org/TR/cors/#access-control-allow-origin-response-header
所示您可以按照他们对该答案的建议,将处理转移到某些中间件层,例如 NGINX 或 Apache,它们可以根据请求中的域动态设置 CORS header,或指定所有子域你会想要在 spring 引导配置中,如果这不是一个无法控制的数量的话。
尽管在问题的第一部分中您声明您接受来自 http://localhost:4200.
的请求,但如果您不需要子域,那么这应该不是问题,那么您可以明确地将那个域列入白名单,还是我理解错了?
我想我找到了一个可行的解决方案。这只是意味着创建一个自定义 CorsConfiguration,覆盖 checkOrigin 方法并创建一个将正确解释 http://*.localhost:4200 的自定义匹配器。代码如下所示:
public class RegexCorsConfiguration extends CorsConfiguration {
private List<String> allowedOriginsRegexes = new ArrayList<>();
/**
* Check the origin of the request against the configured allowed origins.
* @param requestOrigin the origin to check
* @return the origin to use for the response, possibly {@code null} which
* means the request origin is not allowed
*/
public String checkOrigin(String requestOrigin) {
if (!StringUtils.hasText(requestOrigin)) {
return null;
}
if (this.allowedOriginsRegexes.isEmpty()) {
return null;
}
if (this.allowedOriginsRegexes.contains(ALL)) {
if (getAllowCredentials() != Boolean.TRUE) {
return ALL;
} else {
return requestOrigin;
}
}
for (String allowedOriginRegex : this.allowedOriginsRegexes) {
if (createMatcher(requestOrigin, allowedOriginRegex).matches()) {
return requestOrigin;
}
}
return null;
}
public void setAllowedOriginRegex(List<String> allowedOriginsRegexes) {
this.allowedOriginsRegexes = allowedOriginsRegexes;
}
private Matcher createMatcher(String origin, String allowedOrigin) {
String regex = this.parseAllowedWildcardOriginToRegex(allowedOrigin);
Pattern pattern = Pattern.compile(regex);
return pattern.matcher(origin);
}
private String parseAllowedWildcardOriginToRegex(String allowedOrigin) {
String regex = allowedOrigin.replace(".", "\.");
return regex.replace("*", ".*");
}}
当然,从配置 类 中注入 corsConfig,如下所示:
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public CorsWebFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
RegexCorsConfiguration regexCorsConfiguration = new RegexCorsConfiguration();
regexCorsConfiguration.setAllowCredentials(true);
regexCorsConfiguration.setAllowedOriginRegex(corsConfigData.getAllowedOrigins());
regexCorsConfiguration.setAllowedHeaders(corsConfigData.getAllowedHeaders());
regexCorsConfiguration.setAllowedMethods(corsConfigData.getAllowedMethods());
source.registerCorsConfiguration("/**", regexCorsConfiguration);
return new CorsWebFilter(source);
}