记录一次Spring Cloud Gateway配置的跨域处理:解决 ‘Access-Control-Allow-Origin‘ 头包含多个值的问题

发布于:2025-08-03 ⋅ 阅读:(12) ⋅ 点赞:(0)

在微服务架构中,前端与后端分离已经成为一种常见模式。这种模式下,前后端通常会部署在不同的域名或端口上,这就导致了跨域资源共享(CORS)问题。最近,在我们的项目中,我们遇到了这样一个问题:“The 'Access-Control-Allow-Origin' header contains multiple values '*, *', but only one is allowed” 

🛠️ 问题描述

当浏览器发起一个跨域请求时,它首先会发送一个预检请求(OPTIONS),以确定服务器是否允许该跨域请求。然而,在我们的案例中,出现了如下错误提示:❓

The 'Access-Control-Allow-Origin' header contains multiple values '*, *', but only one is allowed

这意味着响应头Access-Control-Allow-Origin被设置了两次,这通常是由于在多个地方配置了CORS支持,例如在每个微服务和网关中分别进行了配置,从而导致冲突。❌

🔧 解决方案

为了解决上述问题,我们需要采取以下两个步骤:

第一步:删除注册到Nacos中的服务中配置的CorsConfig

为了避免重复设置CORS头信息,我们应该从各个微服务中移除任何现有的CORS配置。具体操作如下:

  • 找到并删除所有微服务中的CorsConfig类。
  • 确保这些服务不再自动添加CORS相关的HTTP响应头。

这样做可以确保只有网关负责处理跨域请求,避免了多次设置相同响应头的情况。✅

第二步:在Gateway中配置跨域

接下来,在Spring Cloud Gateway中进行统一的CORS配置。这里提供了一个简单的示例配置:

import org.springframework.context.annotation.Bean;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.reactive.CorsWebFilter;
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;

public class CorsConfig {

    @Bean
    public CorsWebFilter corsFilter() {
        CorsConfiguration config = new CorsConfiguration();
        
        // 设置允许跨域访问的源
        config.addAllowedOrigin("*");
        // 设置允许的方法
        config.addAllowedMethod("*");
        // 设置允许的头信息
        config.addAllowedHeader("*");
        // 允许凭证
        config.setAllowCredentials(true);
        
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", config);

        return new CorsWebFilter(source);
    }
}

这段代码创建了一个全局的CORS过滤器,适用于所有的路由。通过这种方式,我们可以确保每次跨域请求都被正确地处理,而不会出现重复的Access-Control-Allow-Origin响应头。✅

路由规则配置解析

简要解析Spring Cloud Gateway的路由规则定义,以及其如何工作。

- id: admin_route
  uri: lb://mall-admin
  predicates:
    - Path=/api/**
  filters:
    - RewritePath=/api/(?<segment>.*),/mall-admin/${segment}

通过这种配置方式,当客户端发送请求到/api/users时,Gateway首先检查是否符合Path=/api/**条件。如果符合条件,则应用RewritePath过滤器将路径转换为/mall-admin/users,然后根据负载均衡策略将请求转发给mall-admin服务的一个实例进行处理

结论

请注意,尽管上述配置使用了*作为允许的源,但在生产环境中,出于安全考虑,应该明确指定具体的允许源,而不是使用通配符*。此外,如果需要更复杂的CORS策略,如针对不同路径应用不同的CORS规则,则可能需要进一步定制化配置。