You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swagger UI请求绕过Spring Cloud API Gateway直接访问微服务问题

问题解决方案

核心问题原因

Swagger UI发起请求直接访问微服务,是因为微服务生成的Swagger文档中,接口地址未包含网关的路由前缀,且网关端未正确配置Swagger的服务器地址,导致请求跳过网关直接指向微服务实例。


1. 微服务端Swagger配置修正

每个微服务需在Swagger文档中声明网关路由前缀+自身接口路径,确保Swagger UI生成的请求地址自动带上网关前缀。

示例代码(微服务端):

@Configuration
public class SwaggerConfig {
    @Bean
    public OpenAPI customOpenAPI() {
        // 替换为网关对当前微服务的路由前缀,如/api/user、/api/order
        return new OpenAPI()
                .servers(List.of(new Server()
                        .url("/api/user")
                        .description("通过API网关访问用户服务")));
    }
}

2. 网关端Swagger配置修正

原异步收集路由定义的逻辑可能导致Swagger UI加载时地址未初始化完成,改为同步获取;同时添加网关服务器配置,确保请求发往网关入口。

修改后的网关Swagger配置:

@Configuration
public class SwaggerConfig {

    @Autowired
    RouteDefinitionLocator locator;

    private static final String API_URI = "/v3/api-docs";

    @Bean
    public GroupedOpenApi apis(SwaggerUiConfigProperties swaggerUiConfigProperties) {
        Set<AbstractSwaggerUiConfigProperties.SwaggerUrl> urls = new HashSet<>();
        
        // 同步获取所有路由定义,避免异步加载导致的地址缺失
        List<RouteDefinition> routeDefinitions = locator.getRouteDefinitions().collectList().block();
        if (routeDefinitions != null) {
            for (RouteDefinition routeDefinition : routeDefinitions) {
                String resourceName = routeDefinition.getId();
                if (resourceName.contains("-SERVICE")) {
                    // 精准匹配Path类型的路由断言
                    String pattern = routeDefinition.getPredicates().stream()
                            .filter(predicate -> "Path".equals(predicate.getName()))
                            .findFirst()
                            .map(predicate -> predicate.getArgs().get("pattern"))
                            .orElse("");
                    String location = pattern.replace("/**", API_URI);
                    String displayName = resourceName.replace("ReactiveCompositeDiscoveryClient_", "");
                    urls.add(new AbstractSwaggerUiConfigProperties.SwaggerUrl(resourceName, location, displayName));
                }
            }
        }

        swaggerUiConfigProperties.setUrls(urls);

        return GroupedOpenApi.builder()
                .group("resource")
                .pathsToMatch("/api/**")
                .build();
    }

    // 配置网关作为Swagger的默认服务器,确保请求发往网关
    @Bean
    public OpenAPI gatewayOpenAPI() {
        return new OpenAPI()
                .servers(List.of(new Server().url("/")
                        .description("API Gateway 统一入口")));
    }
}

3. 网关路由配置验证

确保网关路由规则正确,将带前缀的请求转发到对应微服务。示例配置(application.yml):

spring:
  cloud:
    gateway:
      routes:
        - id: user-service
          uri: lb://USER-SERVICE # 通过服务发现指向微服务
          predicates:
            - Path=/api/user/** # 网关路由前缀
          filters:
            - StripPrefix=2 # 若微服务自身接口不带/api/user前缀,需移除前2个路径段后转发

4. 统一CORS配置到网关

移除微服务端的CORS配置,仅在网关层处理跨域,避免多端配置冲突:

@Configuration
public class GatewayCorsConfig {
    @Bean
    public CorsWebFilter corsWebFilter() {
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowedOrigins(Collections.singletonList("*"));
        config.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS"));
        config.setAllowedHeaders(Collections.singletonList("*"));
        config.setAllowCredentials(true);

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", config);

        return new CorsWebFilter(source);
    }
}

验证步骤

  1. 启动网关及所有微服务
  2. 访问网关Swagger UI地址(如http://网关地址:端口/swagger-ui.html)
  3. 选择对应微服务文档发起请求,确认请求地址为http://网关地址:端口/api/xxx/接口路径,而非直接访问微服务地址

内容的提问来源于stack exchange,提问作者Akhilesh Magdum

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 10:57:15