Как мне складывать фильтры CORS для разных URL? - PullRequest
0 голосов
/ 27 ноября 2018

У меня есть Spring Rot API REST в качестве бэкэнда для моего приложения React.Веб-сайт и API размещены в разных поддоменах (https://example.com и https://api.example.com соответственно), поэтому я настроил фильтр CORS для поддержки этого:

@Bean
public FilterRegistrationBean corsFilter() {
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();

    CorsConfiguration apiCorsConfig = new CorsConfiguration();
    apiCorsConfig.addAllowedOrigin("https://example.com");
    apiCorsConfig.addAllowedHeader(CorsConfiguration.ALL);
    apiCorsConfig.addAllowedMethod(CorsConfiguration.ALL);
    apiCorsConfig.setMaxAge(600L);
    source.registerCorsConfiguration("/**", apiCorsConfig);

    FilterRegistrationBean filterRegistrationBean =
        new FilterRegistrationBean<>(new CorsFilter(source));
    filterRegistrationBean.setOrder(Ordered.HIGHEST_PRECEDENCE);
    return filterRegistrationBean;
}

Это прекрасно работает.


Теперь я реализовал Spring SAML для поддержки SAML в качестве альтернативного средства аутентификации на основе API.Все конечные точки SAML находятся под /saml/**.Запросы аутентификации SAML могут поступать из любого источника, поэтому мне нужно открыть эти конечные точки, чтобы разрешить запросы CORS из любого источника.

Я попытался сделать следующее:

@Bean
public FilterRegistrationBean corsFilter() {
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();

    CorsConfiguration apiCorsConfig = new CorsConfiguration();
    apiCorsConfig.addAllowedOrigin("https://example.com");
    apiCorsConfig.addAllowedHeader(CorsConfiguration.ALL);
    apiCorsConfig.addAllowedMethod(CorsConfiguration.ALL);
    apiCorsConfig.setMaxAge(600L);
    source.registerCorsConfiguration("/**", apiCorsConfig);

    CorsConfiguration samlCorsConfig = new CorsConfiguration();
    samlCorsConfig.addAllowedOrigin(CorsConfiguration.ALL);
    samlCorsConfig.addAllowedHeader(CorsConfiguration.ALL);
    samlCorsConfig.addAllowedMethod(CorsConfiguration.ALL);
    samlCorsConfig.setMaxAge(600L);
    source.registerCorsConfiguration("/saml/**", samlCorsConfig);

    FilterRegistrationBean filterRegistrationBean =
        new FilterRegistrationBean<>(new CorsFilter(source));
    filterRegistrationBean.setOrder(Ordered.HIGHEST_PRECEDENCE);
    return filterRegistrationBean;
}

Однако этоне работает, и 403 Invalid CORS request возвращается, когда неизвестный источник пытается получить доступ к /saml/** конечным точкам.


Я предполагаю, что проблема в том, что более общий шаблон /** имеет приоритет, дажекогда существует более конкретный муравьиный шаблон /saml/**, соответствующий запросу.

Я не хочу явно настраивать все другие конечные точки, чтобы разрешить отправку сайта, но хочу, чтобы он был универсальным для запросовне соответствует ни одной другой конфигурации CORS.


Как я могу разрешить любому источнику доступ к /saml/**, в то же время позволяя https://example.com получать доступ ко всем остальным точкам /**?

Ответы [ 2 ]

0 голосов
/ 27 ноября 2018

CorsConfiguration регистрируются путем добавления их к LinkedHashMap внутри UrlBasedCorsConfigurationSource.Это означает, что порядок сохраняется, и это просто вопрос добавления CorsConfiguration s в правильном порядке:

@Bean
public FilterRegistrationBean corsFilter() {
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();

    CorsConfiguration samlCorsConfig = new CorsConfiguration();
    samlCorsConfig.addAllowedOrigin(CorsConfiguration.ALL);
    samlCorsConfig.addAllowedHeader(CorsConfiguration.ALL);
    samlCorsConfig.addAllowedMethod(CorsConfiguration.ALL);
    samlCorsConfig.setMaxAge(600L);
    source.registerCorsConfiguration("/saml/**", samlCorsConfig);

    CorsConfiguration apiCorsConfig = new CorsConfiguration();
    apiCorsConfig.addAllowedOrigin("https://example.com");
    apiCorsConfig.addAllowedHeader(CorsConfiguration.ALL);
    apiCorsConfig.addAllowedMethod(CorsConfiguration.ALL);
    apiCorsConfig.setMaxAge(600L);
    source.registerCorsConfiguration("/**", apiCorsConfig);

    FilterRegistrationBean filterRegistrationBean =
        new FilterRegistrationBean<>(new CorsFilter(source));
    filterRegistrationBean.setOrder(Ordered.HIGHEST_PRECEDENCE);
    return filterRegistrationBean;
}
0 голосов
/ 27 ноября 2018

вы можете расширить UrlBasedCorsConfigurationSource и переопределить getCorsConfiguration:

public class CustomeUrlBasedCorsConfigurationSource extend UrlBasedCorsConfigurationSource{

        @Override
        @Nullable
        public CorsConfiguration getCorsConfiguration(HttpServletRequest request) {
            String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
            if(this.pathMatcher.match("/saml/**",lookupPath)){
              return this.corsConfigurations.get("/saml/**");
             }
            return super.getCorsConfiguration(request);
    }   

ваша конфигурация должна выглядеть примерно так:

@Bean
public FilterRegistrationBean corsFilter() {
    CustomeUrlBasedCorsConfigurationSource source = new CustomeUrlBasedCorsConfigurationSource();

    CorsConfiguration apiCorsConfig = new CorsConfiguration();
    apiCorsConfig.addAllowedOrigin("https://example.com");
    apiCorsConfig.addAllowedHeader(CorsConfiguration.ALL);
    apiCorsConfig.addAllowedMethod(CorsConfiguration.ALL);
    apiCorsConfig.setMaxAge(600L);
    source.registerCorsConfiguration("/**", apiCorsConfig);

    CorsConfiguration samlCorsConfig = new CorsConfiguration();
    samlCorsConfig.addAllowedOrigin(CorsConfiguration.ALL);
    samlCorsConfig.addAllowedHeader(CorsConfiguration.ALL);
    samlCorsConfig.addAllowedMethod(CorsConfiguration.ALL);
    samlCorsConfig.setMaxAge(600L);
    source.registerCorsConfiguration("/saml/**", samlCorsConfig);

    FilterRegistrationBean filterRegistrationBean =
        new FilterRegistrationBean<>(new CorsFilter(source));
    filterRegistrationBean.setOrder(Ordered.HIGHEST_PRECEDENCE);
    return filterRegistrationBean;
}
...