在 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 中无效!

相关推荐
1710orange2 小时前
java设计模式:工厂方法 + 建造者模式
java·设计模式
The Open Group3 小时前
TOGAF® 架构库的隐藏力量:现代知识资产战略
微服务·云原生·架构
我不是混子3 小时前
什么是Java 的 Lambda 表达式?
java·后端
小蝙蝠侠3 小时前
JMeter 执行流程
java·jmeter
程序员小假4 小时前
我们来说一说 ThreadLocal 内存泄漏
java·后端
xq95274 小时前
获取Facebook 散列利器 来了 十六进制到 Base64 转换器
java
我不是混子4 小时前
聊聊Spring事件机制
java·后端
DKPT4 小时前
JVM栈溢出时如何dump栈信息?
java·jvm·笔记·学习·spring
DKPT4 小时前
JVM堆大小如何设置?
java·开发语言·jvm·笔记·学习