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 вещи:
-
allowedOrigins не может быть *, если allowCredentials истинно. Это описано на сайте Mozilla.org.
-
Удалите 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;