为 Spring 云网关配置 CORS 策略

Configure CORS policy for Spring Cloud Gateway

我在单独的服务器上有 Spring 云网关 运行,配置如下:

spring:
  cloud:
    gateway:
      globalcors:
        cors-configurations:
          '[/*]':   (I also tried '[/**]':)
            allowedOrigins: "http://localhost:3000"
            allowedMethods:
              - GET
              - POST

但每次从 React 应用程序我得到:

Access to XMLHttpRequest at 'http://11.1.1.1:8080/api/support/tickets/create' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

你知道如何解决 Spring Boot 2.6.2/Spring cloud 2021.0.0 的这个问题吗?

完整代码:http://www.github.com/rcbandit111/Spring_Cloud_Gateway_POC

POST 要求:

Request URL: http://1.1.1.1:8080/api/merchants/onboarding/bank_details
Referrer Policy: strict-origin-when-cross-origin
Accept: application/json, text/plain, */*
Content-Type: application/json
Referer: http://localhost:3000/
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36

Post request Payload:
{"currency":"HNL","iban":"dssvsdvsdv"}

OPTIONS 请求:

Request URL: http://1.1.1.1:8080/api/merchants/onboarding/bank_details
Request Method: OPTIONS
Status Code: 403 Forbidden
Remote Address: 1.1.1.1:8080
Referrer Policy: strict-origin-when-cross-origin

回复:

HTTP/1.1 403 Forbidden
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
content-length: 0

OPTIONS 请求 headers:

OPTIONS /api/merchants/onboarding/bank_details HTTP/1.1
Host: 1.1.1.1:8080
Connection: keep-alive
Accept: */*
Access-Control-Request-Method: POST
Access-Control-Request-Headers: content-type
Origin: http://localhost:3000
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36
Sec-Fetch-Mode: cors
Referer: http://localhost:3000/
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9

查看 section entitled Simple requests in the MDN Web Docs about CORS:

The only type/subtype combinations allowed for the media type specified in the Content-Type header are:

  • application/x-www-form-urlencoded
  • multipart/form-data
  • text/plain

因为您将值 application/json 用于请求的 Content-Type header,所以您需要在 CORS 配置中允许 header:

cors-configurations:
  '[/**]':
    allowedOrigins: "http://localhost:3000"
    allowedMethods:
      - GET
      - POST
    allowedHeaders:
      - Content-Type

我遇到了类似的问题,我做了以下操作:

我的 application.yml 包含将 CORS 配置添加到每个路由:

spring:
  cloud:
    gateway:
      globalcors:
        add-to-simple-url-handler-mapping: true

然后我配置了一个 spring 标准的 CorsWebFilter Bean。请注意,对于生产,您不应将 * 用于 AllowedOrigins 属性。对于开发目的,这非常好。

@Configuration
public class CorsConfiguration extends org.springframework.web.cors.CorsConfiguration {

  @Bean
  public CorsWebFilter corsFilter() {
    org.springframework.web.cors.CorsConfiguration corsConfiguration = new org.springframework.web.cors.CorsConfiguration();
    corsConfiguration.setAllowCredentials(true);
    corsConfiguration.addAllowedOrigin("*");
    corsConfiguration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS", "HEAD"));
    corsConfiguration.addAllowedHeader("origin");
    corsConfiguration.addAllowedHeader("content-type");
    corsConfiguration.addAllowedHeader("accept");
    corsConfiguration.addAllowedHeader("authorization");
    corsConfiguration.addAllowedHeader("cookie");
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    source.registerCorsConfiguration("/**", corsConfiguration);
    return new CorsWebFilter(source);
  }
}

注意:我有版本 2.3。9.Release 用于 spring 启动和 spring 云版本是 Hoxton.SR10。

您 运行 您的 FE 应用程序是否通过 --proxy-conf 重定向?我不太精通 FE,但不要使用 changeOrigin: true。如果您必须使用 changeOrigin: true,它仅适用于 GET,而对于其他人,您可能必须执行类似 this 的操作。 要使用 proxy-conf,我们通常有一个 proxy.conf.json 这样的东西:

{
  "/api/*": {
    "target": "http://external-gateway-url",
    "secure": false,
    "logLevel": "debug"
  }
}

然后 运行 应用程序使用 --proxy-config proxy.conf.json。我的有限元知识已经过时了。您可能希望看起来像 this.

如果不是,并且调用是直接的,则只需在网关中进行以下配置(代理也需要)即可:

spring:
  cloud:
    gateway:
      globalcors:
        corsConfigurations:
          '[/**]':
            allowedOrigins: "http://localhost:3000"
            allowedHeaders: "*"
            allowedMethods:
            - GET
            - POST