在 Spring Cloud Gateway 中实现跨域(CORS)的两种主要方式

在 Spring Cloud Gateway 中实现跨域(CORS)主要有 两种方式

  1. 通过配置类方式(推荐) - 使用 CorsWebFilter
  2. 通过配置文件方式(YAML/Properties)

🚀 推荐方式:使用 CorsWebFilter 配置类(更灵活、可控)

✅ 为什么推荐?

  • 精确控制跨域行为(路径、方法、Header 等)
  • 支持动态配置(如从数据库读取)
  • 与 Spring WebFlux 完全兼容(Gateway 基于 WebFlux)
  • 不依赖路由配置,全局生效或按需生效

📌 完整示例:使用 CorsWebFilter 实现跨域

第一步:创建跨域配置类

java 复制代码
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.reactive.CorsWebFilter;
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;

/**
 * Spring Cloud Gateway 跨域配置类
 * 
 * 说明:
 * - 本配置使用 CorsWebFilter 实现全局跨域支持
 * - 适用于 Spring Cloud Gateway 2020.0.0 及以上版本(基于 Spring WebFlux)
 * - 该 Filter 会在请求进入路由之前生效,确保 OPTIONS 预检请求被正确处理
 */
@Configuration(proxyBeanMethods = false)
public class CorsConfig {

    /**
     * 创建 CorsWebFilter Bean,用于处理跨域请求
     * 
     * @return 配置好的 CorsWebFilter 实例
     */
    @Bean
    public CorsWebFilter corsWebFilter() {
        // 1. 创建 CorsConfiguration 对象,用于定义跨域规则
        CorsConfiguration corsConfiguration = new CorsConfiguration();

        // 2. 允许的请求来源(Origin)
        // 注意:生产环境不要使用 "*",应明确指定可信域名
        corsConfiguration.addAllowedOriginPattern("*"); // Spring Boot 2.4+ 推荐使用 addAllowedOriginPattern 代替 addAllowedOrigin
        // 如果你使用的是较老版本(<2.4),请使用:corsConfiguration.addAllowedOrigin("*");

        // 3. 允许携带 Cookie(如果前端需要发送认证信息如 JWT Token)
        corsConfiguration.setAllowCredentials(true);

        // 4. 允许的 HTTP 方法
        corsConfiguration.addAllowedMethod("GET");
        corsConfiguration.addAllowedMethod("POST");
        corsConfiguration.addAllowedMethod("PUT");
        corsConfiguration.addAllowedMethod("DELETE");
        corsConfiguration.addAllowedMethod("OPTIONS");

        // 5. 允许的请求头(Header)
        // 常见的如 Content-Type, Authorization, X-Requested-With 等
        corsConfiguration.addAllowedHeader("*"); // 允许所有请求头(生产环境建议明确列出)

        // 6. 暴露给前端的响应头(可选)
        corsConfiguration.addExposedHeader("Authorization");
        corsConfiguration.addExposedHeader("Content-Disposition");

        // 7. 预检请求(OPTIONS)缓存时间(单位:秒)
        corsConfiguration.setMaxAge(3600L); // 1小时,减少预检请求次数

        // 8. 创建 UrlBasedCorsConfigurationSource,将 CORS 配置应用到所有路径
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", corsConfiguration); // /** 表示匹配所有路径

        // 9. 返回 CorsWebFilter,Spring Gateway 会自动将其加入过滤器链
        return new CorsWebFilter(source);
    }
}

第二步:确保你的 application.yml 中没有冲突配置

yaml 复制代码
spring:
  cloud:
    gateway:
      # 路由配置示例(与跨域无关,仅为完整上下文)
      routes:
        - id: user-service
          uri: lb://user-service
          predicates:
            - Path=/api/user/**
        - id: order-service
          uri: lb://order-service
          predicates:
            - Path=/api/order/**
  # 注意:不要在这里配置 globalcors(除非你选择配置文件方式)

⚠️ 重要提示 :如果你同时使用了 globalcors 配置和 CorsWebFilter,可能会导致冲突。建议只使用一种方式


🔁 替代方案:使用 application.yml 配置(简单但不够灵活)

如果你只需要简单跨域,也可以在 application.yml 中配置:

yaml 复制代码
spring:
  cloud:
    gateway:
      # CORS 跨域配置,CORS 是网关的责任,而不是业务服务的负担
      globalcors:
        cors-configurations:
          '[/**]': # 匹配所有路由路径(/** 表示所有 API 路径都应用此 CORS 规则)
            # 使用 allowed-origin-patterns 替代 allowedOrigins(支持通配符模式,更安全灵活)
            allowed-origin-patterns:
              - "http://localhost:*"      # 开发环境,允许本地开发环境(任意端口)发起跨域请求
              - "https://yourdomain.com"  # 生产环境,允许指定的生产域名访问
              - "https://*.yourcompany.com" # 允许 yourcompany.com 的所有子域名访问
            # 允许的 HTTP 请求方法(前端可以使用这些方法发起跨域请求)
            allowed-methods:
              - GET     # 允许获取资源(如查询用户信息、列表数据等)
              - POST    # 允许提交数据(如创建用户、提交表单等)
              - PUT     # 允许全量更新资源(如修改用户完整信息)
              - DELETE  # 允许删除资源(如删除订单、用户等)
              - OPTIONS # 允许预检请求(浏览器自动发送,用于 CORS 预检,必须包含!)
              - PATCH   # 允许部分更新资源(如只修改用户邮箱或昵称)
            # 允许客户端在跨域请求中携带的自定义请求头(Header)
            # 如果前端请求中包含未在此列出的 Header,浏览器会拦截并报 CORS 错误
            allowed-headers:
              - "Content-Type"       # 允许指定请求体的媒体类型(如 application/json)
              - "Authorization"      # 允许携带认证令牌(如 Bearer JWT Token)
              - "X-Requested-With"   # 常用于标识 AJAX 请求(部分前端框架自动添加)
              - "Accept"             # 允许客户端声明可接受的响应内容类型(如 application/json)
            # 是否允许跨域请求携带身份凭证(如 Cookie、Authorization Header)
            # 注意:当 allow-credentials 为 true 时,allowed-origin-patterns 不能为 "*"
            allow-credentials: true
            # 预检请求(OPTIONS)的缓存时间(单位:秒)
            # 浏览器在该时间内不会再发送 OPTIONS 请求,提升性能
            max-age: 3600  # 缓存 1 小时(3600 秒)

注意 :在最新版本的 Spring Cloud Gateway 中,spring.cloud.gateway.globalcors.cors-configurations 被标记为:弃用的配置属性,IDEA 提示推荐使用 spring.cloud.gateway.server.webflux.globalcors.cors-configurations

yaml 复制代码
spring:
  cloud:
    gateway:
      server:
        webflux:
          # CORS 跨域配置,CORS 是网关的责任,而不是业务服务的负担
          globalcors:
            cors-configurations:
              '[/**]': # 匹配所有路由路径(/** 表示所有 API 路径都应用此 CORS 规则)
                # 使用 allowed-origin-patterns 替代 allowedOrigins(支持通配符模式,更安全灵活)
                allowed-origin-patterns:
                  - "http://localhost:*"      # 开发环境,允许本地开发环境(任意端口)发起跨域请求
                  - "https://yourdomain.com"  # 生产环境,允许指定的生产域名访问
                  - "https://*.yourcompany.com" # 允许 yourcompany.com 的所有子域名访问
                # 允许的 HTTP 请求方法(前端可以使用这些方法发起跨域请求)
                allowed-methods:
                  - GET     # 允许获取资源(如查询用户信息、列表数据等)
                  - POST    # 允许提交数据(如创建用户、提交表单等)
                  - PUT     # 允许全量更新资源(如修改用户完整信息)
                  - DELETE  # 允许删除资源(如删除订单、用户等)
                  - OPTIONS # 允许预检请求(浏览器自动发送,用于 CORS 预检,必须包含!)
                  - PATCH   # 允许部分更新资源(如只修改用户邮箱或昵称)
                # 允许客户端在跨域请求中携带的自定义请求头(Header)
                # 如果前端请求中包含未在此列出的 Header,浏览器会拦截并报 CORS 错误
                allowed-headers:
                  - "Content-Type"       # 允许指定请求体的媒体类型(如 application/json)
                  - "Authorization"      # 允许携带认证令牌(如 Bearer JWT Token)
                  - "X-Requested-With"   # 常用于标识 AJAX 请求(部分前端框架自动添加)
                  - "Accept"             # 允许客户端声明可接受的响应内容类型(如 application/json)
                # 是否允许跨域请求携带身份凭证(如 Cookie、Authorization Header)
                # 注意:当 allow-credentials 为 true 时,allowed-origin-patterns 不能为 "*"
                allow-credentials: true
                # 预检请求(OPTIONS)的缓存时间(单位:秒)
                # 浏览器在该时间内不会再发送 OPTIONS 请求,提升性能
                max-age: 3600  # 缓存 1 小时(3600 秒)

注意 :YAML 方式在 Spring Cloud Gateway 2020.0.0+ 中仍然有效,但 无法处理复杂逻辑(如动态来源、条件判断等)。


🧪 测试跨域是否生效

你可以用前端代码测试:

javascript 复制代码
// 前端 JavaScript 测试(浏览器控制台)
fetch('http://localhost:8080/api/user/profile', {
  method: 'GET',
  headers: {
    'Authorization': 'Bearer your-token'
  },
  credentials: 'include' // 如果需要发送 Cookie
})
.then(res => res.json())
.then(data => console.log(data));

同时用 Postman 或 curl 发送 OPTIONS 请求验证:

bash 复制代码
curl -H "Origin: http://localhost:3000" \
     -H "Access-Control-Request-Method: POST" \
     -H "Access-Control-Request-Headers: Authorization" \
     -X OPTIONS http://localhost:8080/api/user/login

如果返回头中包含:

复制代码
Access-Control-Allow-Origin: http://localhost:3000
Access-Control-Allow-Methods: GET,POST,PUT,DELETE,OPTIONS
Access-Control-Allow-Credentials: true

说明跨域配置成功!


✅ 最佳实践建议

项目 建议
生产环境 Origin 不要使用 *,应明确列出可信域名,如 http://yourdomain.com
Allow Credentials 如果使用 JWT Token 放在 Header,可设为 true;若用 Cookie 认证,必须为 true
Allowed Headers 生产环境建议明确列出,如 Authorization, Content-Type, X-Requested-With
配置方式选择 优先使用 CorsWebFilter 配置类,便于维护和扩展

📚 总结

  • 推荐方式 :使用 @Configuration + CorsWebFilter(本文第一种方式)
  • 适用场景:所有 Spring Cloud Gateway 项目(2020.0.0+)
  • 优势:灵活、安全、可编程、与 WebFlux 完美集成

💡 提示:Spring Cloud Gateway 是响应式架构(基于 WebFlux),不要使用 Spring MVC 的 @CrossOriginWebMvcConfigurer,它们在 Gateway 中无效!

相关推荐
せいしゅん青春之我19 小时前
[JavaEE初阶]网络协议-状态码
java·网络协议·http
摇滚侠19 小时前
Spring Boot 3零基础教程,WEB 开发 内容协商 接口返回 YAML 格式的数据 笔记35
spring boot·笔记·后端
shepherd11119 小时前
JDK源码深潜(一):从源码看透DelayQueue实现
java·后端·代码规范
天天摸鱼的java工程师19 小时前
SpringBoot + OAuth2 + Redis + MongoDB:八年 Java 开发教你做 “安全不泄露、权限不越界” 的 SaaS 多租户平台
java·后端
鹿里噜哩19 小时前
Nacos跨Group及Namespace发现服务
java·spring cloud
一个处女座的暖男程序猿19 小时前
若依微服务 nacos的配置文件
微服务·云原生·架构
沐浴露z19 小时前
【JVM】详解 对象的创建
java·jvm
weixin_4454766819 小时前
Java并发编程——提前聊一聊CompletableFuture和相关业务场景
java·并发·异步
ChinaRainbowSea19 小时前
11. Spring AI + ELT
java·人工智能·后端·spring·ai编程
不会写DN19 小时前
用户头像文件存储功能是如何实现的?
java·linux·后端·golang·node.js·github