Spring Global CORS не работает, но конфигурация уровня контроллера

Я пытаюсь настроить CORS глобально через WebMvcConfigurerAdapter показанный ниже. Чтобы проверить, я ударил свою конечную точку API через приложение небольшого узла, которое я создал для эмуляции внешней службы. Когда я пытаюсь использовать этот подход, ответ не содержит правильных заголовков и

XMLHttpRequest cannot load http://localhost:8080/api/query/1121. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:333' is therefore not allowed access.

Глобальная конфигурация

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

@EnableWebMvc
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
        @Override
        public void addCorsMappings(CorsRegistry registry) {
            registry.addMapping("/api/query/**")
                    .allowedOrigins("*")
                    .allowedHeaders("*")
                    .allowCredentials(true);
        }
}

Однако, когда я использую аннотацию @CrossOrigin так что она отлично работает с соответствующими заголовками.

@CrossOrigin(origins = "*", allowCredentials = "true", allowedHeaders = "*")
@RestController
@RequestMapping(value = "/api/query", produces = MediaType.APPLICATION_JSON_VALUE)
public class QueryController {
   ......
}

Производит

Access-Control-Allow-Credentials:true
Access-Control-Allow-Origin:http://localhost:333

Что мне не хватает, чтобы сделать глобальную конфигурацию (следуйте инструкциям здесь https://spring.io/blog/2015/06/08/cors-support-in-spring-framework). Я чувствую, что мне не хватает чего-то простого, так как аннотация контроллера работает нормально.

Ответ 1

Для того чтобы глобальная конфигурация CORS работала, клиент должен добавить эти два заголовка в запрос OPTIONS.

Origin: http://host.com
Access-Control-Request-Method: POST

Однако для аннотации @CrossOrigin требуется только заголовок "Origin".
Возможно, ваш клиент добавляет заголовок "Origin", но отсутствует "Access-Control-Request-Method"..... вот почему он работает для вас с @CrossOrigin, но не с глобальной конфигурацией.

Ответ 2

вы не объявили в нем метод, который по умолчанию принимает только метод get. попробуйте registry.allowedMethods("*");

Ответ 3

Я смог получить конфигурацию Spring Global CORS, после того как вы столкнулись с конкретной проблемой, описанной в этой проблеме. Мне пришлось сделать 2 вещи:

  1. allowedOrigins не может быть *, если allowCredentials истинно. Это описано на сайте Mozilla.org.

  2. Удалите mvc: аннотация, управляемая из весеннего XML. Не может иметь BOTH конфигурацию XML и @EnableWebMvc. Глобальный класс не будет работать без @EnableWebMvc, поэтому mvc: аннотация должна быть удалена.

Ответ 4

Я столкнулся с подобной проблемой. Я изменил WebMvcConfigurerAdapter на WebMvcConfigurationSupport и начал работать.

В дополнение к этому я также переместил RequestMappingHandlerMapping, определенный в файле конфигурации xml, в конфигурацию java.

Ответ 5

У меня точно такая же проблема, но ни одно из решений в этой теме не работает. Мне удалось решить это с помощью следующего:

Новый компонент конфигурации:

@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class CorsFilterConfiguration {

  @Bean
  public CorsFilter corsFilter() {
      UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
      CorsConfiguration config = new CorsConfiguration();
      config.setAllowCredentials(true);
      config.addAllowedOrigin("*");
      config.setAllowedMethods(Arrays.asList("POST", "OPTIONS", "GET", "DELETE", "PUT"));
      config.setAllowedHeaders(Arrays.asList("X-Requested-With", "Origin", "Content-Type", "Accept", "Authorization"));
      source.registerCorsConfiguration("/**", config);
      return new CorsFilter(source);
  }
}

Модификация моего web.xml для добавления нового фильтра для всех URL:

<filter>
  <filter-name>corsFilter</filter-name>
  <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
  <filter-name>corsFilter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

Очевидно, что вы можете изменить конфигурацию Cors соответственно.

Ответ 6

Я думаю, что в вашем определении отображения отсутствует *:

registry.addMapping("/api/query/**")

Без этой дополнительной * эта конфигурация не отображается на путь /api/query/1121 (но она будет работать в /api/query/5).

Ответ 7

У меня была похожая проблема, и ни один из методов не работал (кроме использования аннотации @CrossOrigin для каждого контроллера). Я следовал решению Бхарата Сингха выше и после некоторой отладки внутренних компонентов Spring Framework - вот что сработало для меня (Spring Boot 2.0.6 + Spring Framework 5.0.10):

@Configuration
public class WebMvcConfiguration extends WebMvcConfigurationSupport {

/* (non-Javadoc)
 * @see org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport#addCorsMappings(org.springframework.web.servlet.config.annotation.CorsRegistry)
 */
@Override
protected void addCorsMappings(CorsRegistry registry) {
    //NOTE: servlet context set in "application.properties" is "/api" and request like "/api/session/login" resolves here to "/session/login"!
    registry.addMapping("/**")
        .allowedMethods("GET", "POST", "PUT", "DELETE")
        .allowedOrigins("*")
        .allowedHeaders("*")
        .allowCredentials(false);
    }
}

Первоначально, когда я использовал отображение "/api/**" оно было настроено в Spring, но поскольку приложение было развернуто с контекстом "/api" - запросы типа "/api/session/login" были внутренне сопоставлены с "/session/login" и такое сопоставление в конфигурации CORS не найдено - обратите на это внимание!

Ответ 8

Я столкнулся с той же проблемой, и после установки атрибута maxAge все стало работать нормально!

@Bean
public WebMvcConfigurer CORSConfigurer() {
    return new WebMvcConfigurer() {
        @Override
        public void addCorsMappings(CorsRegistry registry) {
            registry.addMapping("/**")
                    .allowedOrigins("*")
                    .allowedHeaders("*")
                    .allowedMethods("GET", "POST", "PUT", "DELETE", "HEAD")
                    .maxAge(-1)   // add maxAge
                    .allowCredentials(false);
        }
    };
}

если вы проверите аннотацию CrossOrigin, этому атрибуту будет присвоено значение по умолчанию

/**
 * <p>By default this is set to {@code 1800} seconds (30 minutes).
 */
long maxAge() default -1;