【问题标题】:Spring Boot CORS configuration issue - Access-Control-Request-Method: POSTSpring Boot CORS 配置问题 - 访问控制请求方法:POST
【发布时间】:2019-05-28 18:10:55
【问题描述】:

我有一个 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 spring-boot cors spring-web


【解决方案1】:

在允许的方法中添加“选项”

  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);
    }

【讨论】:

  • 我正在尝试通过配置而不是自定义过滤器来做到这一点。
【解决方案2】:

Spring MVC 全局 CORS 配置在我写的 that blog postSpring Framework reference documentation 中进行了描述。

如果您enable CORS support at Spring Security level,Spring Security 将自动检测 Spring MVC CORS 配置并利用它来授权请求​​。

【讨论】:

    【解决方案3】:

    同样的问题让我们有些头疼,但我们设法使用 Spring-Boot v2.3.3 找到了解决方案。这里的问题是带有OriginAccess-control-request-method 标头的选项请求可以正常工作,只要您:

    1. WebMvcConfigurer 中配置 CORS。
    2. allowedMethods 中定义OPTIONS
    3. 请勿添加任何其他 CorsFilter。

    例如

    @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。在this answer 中找到的解决方案是添加一个 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 后一切正常。

    【讨论】:

      猜你喜欢
      • 2021-02-13
      • 2020-01-07
      • 2021-04-11
      • 2020-10-20
      • 2020-12-20
      • 2021-12-18
      • 2016-12-21
      • 2019-12-26
      • 2017-03-12
      相关资源
      最近更新 更多