Skip to content

CORS 配置 (CORS Configuration)

你可以配置网关来全局地或按路由地控制 CORS(跨源资源共享)行为。两者提供的配置能力是相同的。

1. 全局 CORS 配置

“全局” CORS 配置是一个将 URL 模式映射到 Spring Framework CorsConfiguration 的映射表。

以下示例配置了全局 CORS:

application.yml

yaml
spring:
  cloud:
    gateway:
      globalcors:
        cors-configurations:
          '[/**]':
            allowedOrigins: "https://docs.spring.io"
            allowedMethods:
            - GET

在上面的示例中,所有路径(/**)都允许来自 docs.spring.io 的 GET 请求进行跨源访问。

对于那些未被任何网关路由断言匹配处理的请求,如果你也想提供相同的 CORS 配置,请将 spring.cloud.gateway.globalcors.add-to-simple-url-handler-mapping 属性设置为 true。当你尝试支持 CORS 预检请求(preflight requests) 且由于 HTTP 方法是 OPTIONS 导致你的路由断言计算结果不为 true 时,这非常有用。

2. 路由级 CORS 配置

“路由级”配置允许通过元数据(Metadata)键 cors 直接将 CORS 配置应用于某个特定路由。与全局配置一样,这些属性属于 Spring Framework CorsConfiguration

::: note 注意 如果路由中没有 Path 断言,将默认应用 /**。 :::

application.yml

yaml
spring:
  cloud:
    gateway:
      routes:
      - id: cors_route
        uri: https://example.org
        predicates:
        - Path=/service/**
        metadata:
          cors:
            allowedOrigins: '*'
            allowedMethods:
              - GET
              - POST
            allowedHeaders: '*'
            maxAge: 30

补充教学 —— 彻底搞懂网关 CORS

1. 什么是 CORS?(为什么要配置它?) CORS 是浏览器的同源策略(Same-Origin Policy)的一部分。如果你的前端代码(如 localhost:3000)去请求不同域名/端口的网关(如 api.example.com),浏览器会出于安全考虑拦截返回结果,除非网关明确告诉浏览器“我允许这个源访问”。

2. 预检请求 (Preflight) 与 OPTIONS 方法 对于一些“复杂”请求(比如带自定义 Header、或者是 PUT/DELETE),浏览器会先发一个 OPTIONS 请求问问网关。

  • 痛点:如果你在路由里配置了 Method=POST,那么这个 OPTIONS 预检请求就会因为不匹配路由而导致 404。
  • 解法:配置 add-to-simple-url-handler-mapping: true。这会让网关在路由匹配之前先处理这些 OPTIONS 请求,从而正确响应 CORS 头部。

3. 常见属性说明

  • allowedOrigins:允许哪些域名访问(生产环境千万不要写 *)。
  • allowedMethods:允许哪些 HTTP 方法。
  • allowedHeaders:允许客户端传哪些自定义 Header。
  • allowCredentials:是否允许携带 Cookie(如果设为 true,allowedOrigins 不能为 *)。
  • maxAge:告诉浏览器在多少秒内不需要再次发起预备请求。

4. 应该在网关配还是后端服务配?首选在网关配置。 如果网关配置了 CORS,后端服务就不需要再配置了。如果两边都配了,可能会导致 Header 冲突(比如出现两个重复的 Access-Control-Allow-Origin 导致浏览器依然报错)。

最佳实践: 一次性在 globalcors 下配置好全站的默认策略,如果有极个别特殊路由需要不同的权限,再使用路由级配置。

Based on Spring Framework.