在CORS Spring Security + WebFlux中启用通配符

时间:2018-11-21 12:36:19

标签: spring-boot spring-security spring-webflux

我在使用spring webFlux制作的项目中具有spring security + CORS enable。我的问题是,我们接受来自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);
}

你有什么想法吗?

2 个答案:

答案 0 :(得分:2)

我认为,如responses to this question,所示,CORS规范不允许通配符子域。具体请参见https://www.w3.org/TR/cors/#access-control-allow-origin-response-header

您可以按照他们的建议,将处理过程移至某些中间件层(如NGINX或Apache),它们可以根据请求中的域动态设置CORS标头,或在所需的子域中指定所有子域spring boot config,如果这不算总数的话。

尽管,在问题的第一部分中,您声明接受了http://localhost:4200.的请求,如果您不需要子域,那么这不成问题,那么您可以将一个域明确地白名单,或者我误会了吗?

答案 1 :(得分:0)

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