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); } }
验证步骤
- 启动网关及所有微服务
- 访问网关Swagger UI地址(如
http://网关地址:端口/swagger-ui.html) - 选择对应微服务文档发起请求,确认请求地址为
http://网关地址:端口/api/xxx/接口路径,而非直接访问微服务地址
内容的提问来源于stack exchange,提问作者Akhilesh Magdum
相关产品推荐
相关产品推荐

