Подтвердить что ты не робот

Spring Отдых и Корс

Я разрабатываю приложение загрузки Spring с интерфейсом Rest и выталкиванием дротиков.

XMLHttpRequest выполняет запрос OPTIONS, который обрабатывается полностью корректно. После этого выдается окончательный запрос GET ( "/products" ) и не выполняется:

Нет заголовка "Access-Control-Allow-Origin" присутствует на запрошенном ресурсе. Происхождение http://localhost:63343 ', следовательно, не допускается.

После некоторой отладки я нашел следующее: Функция AbstractHandlerMapping.corsConfiguration заполняется для всех подклассов, кроме репозиторияRestHandlerMapping. В RepositoryRestHandlerMapping no corsConfiguration присутствует/задано во время создания и поэтому не будет распознаваться как путь/ресурс cors.
= > Нет заголовков CORS
Может ли это быть проблема? Как я могу установить его?

Конфигурационные классы:

@Configuration
public class RestConfiguration extends RepositoryRestMvcConfiguration {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**").allowCredentials(false).allowedOrigins("*").allowedMethods("PUT", "POST", "GET", "OPTIONS", "DELETE").exposedHeaders("Authorization", "Content-Type");
    }

   ...
}

Я даже попытался установить Cors для аннотации:

@CrossOrigin( methods = RequestMethod.GET, allowCredentials = "false")
public interface ProductRepository extends CrudRepository<Product, String> {


}

Заголовки необработанных запросов:

GET /products HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Cache-Control: max-age=0
authorization: Basic dXNlcjpwYXNzd29yZA==
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/43.0.2357.130 Chrome/43.0.2357.130 Safari/537.36
Content-Type: application/json
Accept: */*
Referer: http://localhost:63343/inventory-web/web/index.html
Accept-Encoding: gzip, deflate, sdch
Accept-Language: de-DE,de;q=0.8,en-US;q=0.6,en;q=0.4

Заголовки исходного ответа:

HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Type: application/hal+json;charset=UTF-8
Transfer-Encoding: chunked
Date: Thu, 30 Jul 2015 15:58:03 GMT

Используемые версии: Spring Загрузка 1.3.0.M2 Spring 4.2.0.RC2

Что мне не хватает?

4b9b3361

Ответ 1

Действительно, до Spring Data REST 2.6 (Ingalls) только HandlerMapping экземпляры, созданные Spring MVC WebMvcConfigurationSupport, а контроллеры, аннотированные с помощью @CrossOrigin, были осведомлены о CORS.

Но теперь, когда DATAREST-573 исправлено, RepositoryRestConfiguration теперь предоставляет getCorsRegistry() для глобальной настройки и @CrossOrigin аннотации на репозитории также признаны, поэтому это рекомендуемый подход. См. fooobar.com/questions/120072/... ответ для конкретных примеров.

Для людей, которым приходится придерживаться Spring Data REST 2.5 (Hopper) или предыдущих версий, я считаю, что лучшим решением является использование подхода на основе фильтра. Вы, очевидно, могли бы использовать Tomcat, Jetty или этот, но имейте в виду, что Spring Framework 4.2 также предоставляет CorsFilter, которые используют ту же логику обработки CORS, что и подходы @CrossOrigin и addCorsMappings(CorsRegistry registry). Передав экземпляр UrlBasedCorsConfigurationSource в конструктор CorsFilter, вы можете легко получить что-то столь же мощное, как Spring внутренняя глобальная поддержка CORS.

Если вы используете Spring Boot (который поддерживает Filter beans), это может быть что-то вроде:

@Configuration
public class RestConfiguration {

    @Bean
    public FilterRegistrationBean corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration().applyPermitDefaultValues();
        source.registerCorsConfiguration("/**", config);
        FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
        bean.setOrder(0);
        return bean;
    }
}

Ответ 2

Так как был реализован поезд Ingalls, поддержка CORS в Spring Теперь данные. Есть два способа решения:

  • Аннотация @CrossOrigin с указанием origins, methods и allowedHeaders над интерфейсом @RepositoryRestResource.

    @CrossOrigin(...)
    @RepositoryRestResource
    public interface PageRepository extends CrudRepository<Page, Long> { ... }
    
  • Глобальная конфигурация с RepositoryRestConfiguration внутри класса @Configuration. Маркировка репозиториев с помощью @CrossOrigin не требуется.

    @Configuration
    public class GlobalRepositoryRestConfigurer extends RepositoryRestConfigurerAdapter {
    
        @Override
        public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
            config.getCorsRegistry()
                      .addMapping(CORS_BASE_PATTERN)
                      .allowedOrigins(ALLOWED_ORIGINS)
                      .allowedHeaders(ALLOWED_HEADERS)
                      .allowedMethods(ALLOWED_METHODS);
         }
    
    }
    

Ответ 3

По какой-то причине подход, предложенный в принятом ответе выше, не работал у меня после обновления с Spring Boot 1.5.2 до 1.5.6.

Как также отмечено комментарием @BigDong, исключение, которое я получил, было:

BeanInstantiationException: Не удалось создать экземпляр [javax.servlet.Filter]: Factory метод 'springSecurityFilterChain' сделал исключение; вложенное исключение - org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean с именем 'corsFilter', как ожидается, будет иметь тип 'org.springframework.web.filter.CorsFilter', но на самом деле имеет тип 'org.springframework.boot.web.servlet.FilterRegistrationBean

Итак, вот что я нашел, чтобы получить "глобальную" конфигурацию CORS для всех конечных точек в нашем REST API, независимо от того, реализованы ли они с помощью Spring Data Rest или Spring MVC, причем все конечные точки защищены Spring Безопасность.

Мне не удалось подключить CorsFilter к конвейеру запроса в правой части, поэтому вместо этого я сконфигурировал SDR и MVC отдельно, однако используя эту конфигурацию для своих CorsRegistry через этот помощник:

public static void applyFullCorsAllowedPolicy(CorsRegistry registry) {
    registry.addMapping("/**") //
            .allowedOrigins("*") //
            .allowedMethods("OPTIONS", "HEAD", "GET", "PUT", "POST", "DELETE", "PATCH") //
            .allowedHeaders("*") //
            .exposedHeaders("WWW-Authenticate") //
            .allowCredentials(true)
            .maxAge(TimeUnit.DAYS.toSeconds(1));
}

И затем для MVC:

@Configuration
@EnableWebSecurity(debug = true)
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class CustomWebSecurityConfiguration extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // enables CORS as per
        // https://docs.spring.io/spring-security/site/docs/current/reference/html/cors.html#cors
        http.cors()
            .and() // ...
    }

    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurerAdapter() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                applyFullCorsAllowedPolicy(registry);
            }
        };
    }
}

И затем для SDR:

public class CustomRepositoryRestMvcConfiguration extends RepositoryRestConfigurerAdapter {

@Override
public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
    config.setReturnBodyOnCreate(true);
    config.setReturnBodyForPutAndPost(true);
    config.setReturnBodyOnUpdate(true);
    config.setMaxPageSize(250);
    config.setDefaultPageSize(50);
    config.setDefaultMediaType(MediaTypes.HAL_JSON);
    config.useHalAsDefaultJsonMediaType(true);

    CustomWebSecurityConfiguration.applyFullCorsAllowedPolicy(config.getCorsRegistry());
}

Вот еще одна ссылка на эту тему, которая помогла мне придумать этот ответ: