spring-security 启用CORS spring security中的通配符+ webFlux

3zwjbxry  于 2022-11-11  发布在  Spring
关注(0)|答案(3)|浏览(163)

我在一个用spring webFlux制作的项目中启用了spring security + CORS。我的问题是我们接受了例如来自以下的请求:http://localhost:4200。我如何才能使CORS接受来自http://*.localhost:4200的请求,例如http://a.localhost:4200http://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);
}

你有什么想法吗???

sbtkgmzw

sbtkgmzw1#

我想我找到了一个可行的解决方案。这仅仅意味着创建一个自定义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);
}
g0czyy6m

g0czyy6m2#

我认为,正如responses to this question,中所指出的,CORS规范不允许对子域使用通配符。具体参见https://www.w3.org/TR/cors/#access-control-allow-origin-response-header
您可以遵循他们的建议,将处理转移到NGINX或Apache等中间件层,这些中间件层可以根据请求中的域动态设置CORS头,或者指定您希望在Spring Boot 配置中使用的所有子域,如果这些子域的总数没有达到无法管理的数量的话。
虽然,在你的问题的第一部分,你说你接受来自http://localhost:4200.的请求,这应该不是一个问题,如果你不需要子域,那么你可以明确地白名单,一个域,或我误解了?

owfi6suc

owfi6suc3#

@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());

    //Set allowed patterns here
    config.setAllowedPatterns(List.of("http://*.localhost:4200"));

    source.registerCorsConfiguration("/**", config);
    return new CorsWebFilter(source);
}

从5.3开始,您可以使用setAllowedPatterns替代setAllowedOrigins,它支持更灵活的源模式,除了端口列表外,还可以在主机名中的任意位置使用“*”。

  • https://*. domain1.com--以domain1.com结尾的域
  • https://*. domain1.com:[8080,8081] --在端口8080或端口8081上以domain1.com结尾的域
  • https://*. domain1.com:[*] --在任何端口(包括默认端口)上以domain1.com结尾的域

相关问题