← 返回题目列表

API 网关如何统一处理跨域(CORS)?

高频 中等 第 6 / 25 题 更新于 2026/07/28
API网关跨域CORSSpring Cloud Gateway

简化版

跨域是浏览器同源策略的限制——前端页面向不同源(协议/域名/端口不同)的接口发请求会被拦截。微服务下如果每个服务各自处理跨域,重复且容易不一致。把跨域统一放到网关处理:网关作为统一入口,在这里统一配置 CORS(添加 Access-Control-Allow-Origin 等响应头、处理 OPTIONS 预检请求),所有经过网关的请求都自动获得跨域支持,后端服务不用各自处理。Spring Cloud Gateway 通过 globalcors 全局跨域配置CorsWebFilter 实现。关键要处理好 OPTIONS 预检请求,且注意避免和后端重复添加 CORS 头(会导致头重复报错)。

详细版

为什么在网关统一处理跨域: 网关是统一入口,跨域配置集中一处、所有服务受益、避免各服务重复配置和不一致。

Spring Cloud Gateway 全局跨域配置:

spring:
  cloud:
    gateway:
      globalcors:
        cors-configurations:
          '[/**]':                          # 对所有路径
            allowedOrigins: "https://a.com"  # 允许的源
            allowedMethods: "*"              # 允许的方法
            allowedHeaders: "*"              # 允许的请求头
            allowCredentials: true           # 允许带 Cookie

关键点:

  • 处理 OPTIONS 预检:非简单请求浏览器先发 OPTIONS 探路,网关要正确响应。
  • 避免 CORS 头重复:如果后端服务也加了 CORS 头,会和网关的重复,导致 Access-Control-Allow-Origin 出现多个值而报错——只在网关加一处
  • allowCredentials=true 时 allowedOrigins 不能是 *:带凭证时必须指定具体域名。

完整版教学

一、跨域问题的由来:同源策略

浏览器有一个安全机制叫同源策略:默认只允许网页向同源的地址发请求。「同源」指协议、域名、端口都相同。如果前端页面(https://a.com)向不同源的接口(https://api.b.com)发 AJAX 请求,浏览器会拦截响应——这就是跨域问题

微服务架构下,前端往往要访问部署在不同域名/端口的多个后端服务,跨域是常见需求。解决跨域的标准方案是 CORS(跨域资源共享)——服务端在响应里加特定的头,声明「我允许这个源跨域访问」,浏览器就放行。

二、为什么在网关统一处理跨域

CORS 的头可以在每个后端服务里加,但在微服务下这样做有问题:

  • 重复:每个服务都要写一遍跨域配置。
  • 容易不一致:不同服务的跨域策略可能配得不一样,出问题难排查。
  • 难维护:想调整跨域策略(如加一个允许的域名),要改所有服务。

网关是所有请求的统一入口,把跨域统一放到网关处理最合适:在网关配置一次 CORS,所有经过网关的请求都自动获得跨域支持,后端服务完全不用管跨域。集中、统一、好维护——这是网关「收口公共逻辑」价值的又一体现。

三、CORS 的核心响应头

网关处理跨域,本质是在响应里加这些 CORS 头:

  • Access-Control-Allow-Origin:允许哪个源跨域(具体域名,或 * 允许所有——但带凭证时不能用 *)。
  • Access-Control-Allow-Methods:允许的 HTTP 方法(GET、POST、PUT、DELETE…)。
  • Access-Control-Allow-Headers:允许的自定义请求头。
  • Access-Control-Allow-Credentials:是否允许请求带 Cookie(凭证)。
  • Access-Control-Max-Age:预检结果的缓存时间(多久内不用再预检)。

四、关键:处理 OPTIONS 预检请求

CORS 有简单请求非简单请求之分。对于非简单请求(如带自定义头、PUT/DELETE 方法、Content-Type: application/json),浏览器会先发一个 OPTIONS 请求去「探路」——这叫预检请求(Preflight),询问服务端「我接下来要发的这种跨域请求,你允许吗」。服务端要正确响应 OPTIONS(返回允许的 CORS 头),浏览器确认后才发真正的请求。

网关必须正确处理 OPTIONS 预检请求——识别 OPTIONS 请求,直接返回 CORS 头(不用转发给后端),告诉浏览器允许。Spring Cloud Gateway 的 globalcors 配置会自动处理预检;如果自定义 CorsWebFilter 也要确保 OPTIONS 被正确响应。忘记处理 OPTIONS 是跨域配置最常见的坑——真实请求前的预检没通过,请求根本发不出去。

五、常见坑:CORS 头重复

网关统一处理跨域时,一个高频坑是 CORS 响应头重复

  • 如果网关加了 CORS 头,后端服务也加了 CORS 头(比如后端 Spring MVC 配了 @CrossOrigin 或全局 CORS),那么响应里会出现两个 Access-Control-Allow-Origin
  • 浏览器看到 Access-Control-Allow-Origin 有多个值(或重复),会认为不合法,报错拦截——跨域反而失败了。

解决:跨域只在一个地方配置——既然在网关统一处理了,后端服务就不要再配 CORS(去掉 @CrossOrigin、后端 CORS 配置)。保证 CORS 头只被添加一次。

另一个注意点:allowCredentials=true(允许带 Cookie)时,allowedOrigins 不能是 *,必须指定具体的域名——这是 CORS 规范的安全要求(带凭证的跨域必须明确来源)。

六、常见误区与追问

这道题面试时最容易丢分的地方,是把「网关跨域处理」答成一段泛泛的组件介绍。更稳的答法是先给结论,再沿着 统一流量入口链路 拆清楚流程,最后补上异常场景、数字边界和选型取舍。

回答层次要讲清的内容容易漏掉的边界
核心定义CORS 是浏览器安全策略,网关可统一处理预检请求和跨域响应头不要停在名词解释
流程机制浏览器判断跨域复杂请求 -> 发送 OPTIONS 预检 -> 网关匹配 CORS 规则 -> 返回允许的源方法头 -> 浏览器再发送真实请求说明谁触发、谁存储、谁通知、谁兜底
工程取舍复杂请求会先发 OPTIONS 预检,服务端需返回 Access-Control-Allow-Origin、Methods、Headers 等头网关适合收口横切能力,但不能把业务逻辑堆到网关,否则会形成新的复杂单体
网关跨域处理 面试拆解:
1. 浏览器判断跨域复杂请求
2. 发送 OPTIONS 预检
3. 网关匹配 CORS 规则
4. 返回允许的源方法头
5. 浏览器再发送真实请求

记忆钩子:先拆路由、过滤器、鉴权、限流、熔断、灰度,再说明网关和业务服务的边界;回答时一定要落到题目中的「网关跨域处理」,不要把相邻中间件的能力混着讲。

  • 误区:CORS 是后端服务之间的限制。 CORS 是浏览器实施的安全策略,服务端和网关只是返回允许规则。
  • 误区:设置星号 Origin 一定没问题。 带 Cookie 或凭证时不能简单使用通配符,且生产应限制可信域名。
  • 误区:只处理真实请求就够了。 复杂跨域请求会先发 OPTIONS 预检,预检失败真实请求不会发送。
  • 追问:网关为什么适合统一处理 CORS? 入口统一,避免每个微服务重复配置且规则不一致。
  • 追问:Access-Control-Allow-Credentials 有什么限制? 允许凭证时 Origin 不能是通配符,必须明确返回具体源。
  • 追问:CORS 和 CSRF 是一回事吗? 不是,CORS 控制跨源读取权限,CSRF 是利用用户凭证发起伪造请求。

七、加强记忆

跨域源于浏览器同源策略(协议/域名/端口不同即跨域被拦),标准解法 CORS(服务端加响应头声明允许跨域)。网关统一处理跨域最合适——统一入口配置一次、所有服务受益、避免各服务重复和不一致。Spring Cloud Gateway 用 globalcors 配置CorsWebFilter,加 Access-Control-Allow-Origin/Methods/Headers/Credentials 等头。两个关键坑① 必须处理 OPTIONS 预检请求(非简单请求浏览器先发 OPTIONS 探路,网关要正确响应,否则真实请求发不出——最常见坑);② 避免 CORS 头重复(网关和后端都加会导致 Access-Control-Allow-Origin 多值报错,只在网关配一处、后端去掉 CORS)。另注意 allowCredentials=trueallowedOrigins 不能用 *。口诀:网关统一配 CORS、处理好 OPTIONS 预检、只配一处防头重复