我有一个CORS配置:
@Bean
CorsConfigurationSource corsConfigurationSource() {
LOGGER.info("Configuring CORS");
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("http://localhost:3000", "https://localhost:3000", "http://localhost:2199", "https://localhost:2199"));
configuration.setAllowCredentials(true);
configuration.setAllowedHeaders(
Arrays.asList("Access-Control-Allow-Headers",
"Access-Control-Allow-Origin", "Access-Control-Request-Method",
"Access-Control-Request-Headers", "Origin", "Cache-Control",
"Content-Type", "Authorization", "Accept"));
configuration.setAllowedMethods(
Arrays.asList("DELETE", "GET", "POST", "PATCH", "PUT"));
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
这适用于此请求:
curl -v -XOPTIONS -H 'Access-Control-Request-Headers: content-type' -H 'Origin: http://localhost:3001' http://localhost:8080/auth/create-account
它返回200
如果我添加Access-Control-Request-Method: POST
它不起作用
curl -v -XOPTIONS -H 'Access-Control-Request-Headers: content-type' -H 'Origin: http://localhost:3001' http://localhost:8080/auth/create-account -H 'Access-Control-Request-Method: POST'
这是控制器:
@RestController
@RequestMapping("/auth")
public class AuthEndpoint {
@PostMapping("/login")
public ResponseEntity<Object> doLogin(@RequestBody @Valid LoginDTO loginDTO) {
LOGGER.debug("Attempting login {}", loginDTO);
try {
.....
春天的日志 说:
2019-01-01 21:16:35.100 DEBUG 24848 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : OPTIONS "/auth/create-account", parameters={}
2019-01-01 21:16:35.104 DEBUG 24848 --- [nio-8080-exec-1] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped to public org.springframework.http.ResponseEntity<java.lang.Object> rest.AuthEndpoint.createAccount(NewAccountDTO)
2019-01-01 21:16:35.106 DEBUG 24848 --- [nio-8080-exec-1] o.j.s.OpenEntityManagerInViewInterceptor : Opening JPA EntityManager in OpenEntityManagerInViewInterceptor
2019-01-01 21:16:35.112 DEBUG 24848 --- [nio-8080-exec-1] o.j.s.OpenEntityManagerInViewInterceptor : Closing JPA EntityManager in OpenEntityManagerInViewInterceptor
2019-01-01 21:16:35.112 DEBUG 24848 --- [nio-8080-exec-1] o.s.orm.jpa.EntityManagerFactoryUtils : Closing JPA EntityManager
2019-01-01 21:16:35.112 DEBUG 24848 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Completed 403 FORBIDDEN
看起来调度程序 servlet 正在拦截它并杀死它,但只能使用 Access-Control-Request-Method
标头,没有该标头它可以工作。
现在,如果我更改控制器以添加以下内容:@CrossOrigin(origins = "http://localhost:3000")
两种方式都有效。
我的问题是,如何全局配置我的整个应用程序,以避免使用(应该是冗余的)@CrossOrigin
注释来装饰每个 REST 控制器?
同样的问题让我们有些头疼,但我们设法找到了 Spring-Boot v2.3.3 的解决方案。这里的问题是,Access-control-request-method
Origin
只要您:
- 在
WebMvcConfigurer
中配置 CORS
。 - 在
allowedMethods
中定义OPTIONS
。 - 不要添加任何其他 CorsFilters。
例如
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods(HttpMethod.GET.name(), HttpMethod.HEAD.name(),
HttpMethod.OPTIONS.name(), HttpMethod.POST.name())
.maxAge(1000L); // in seconds
}
}
但是,我们也使用了Swagger v2.9.2,由于某种奇怪的原因,上面的WebMvcConfigurer没有为Swagger /v2/api-docs
端点启用CORS。在此答案中找到的解决方案是添加CorsFilter bean,例如
@Bean
public CorsFilter corsFilterSwagger() {
CorsConfiguration config = new CorsConfiguration();
config.addAllowedOrigin("*");
config.setMaxAge(1000L);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/v2/api-docs", config);
return new CorsFilter(source);
}
问题是,一旦我们添加了它,选项请求就会再次开始失败。最终,我们将 Swagger 升级到版本 3.0.0,其中端点的 CORS 问题已修复,因此在删除 CorsFilter 后一切正常。
在允许的方法中添加"选项"
response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods", "POST, PUT, PATCH, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "Content-Type, Accept, X-Requested-With, remember-me, Authorization, User-Accept-Language");
if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
response.setStatus(HttpServletResponse.SC_OK);
} else {
chain.doFilter(req, res);
}
MVC 全局 CORS 配置在我写的那篇博客文章和 Spring Framework 参考文档中都有描述。
Spring Security将自动检测 Spring MVC CORS 配置,并在 Spring Security 级别启用 CORS 支持时利用它来授权请求。