Docker部署Keycloak搭配Spring Cloud Gateway出现Swagger CORS错误
解决Spring Cloud Gateway + Keycloak环境下Swagger UI的CORS问题
核心问题拆解
你的场景里CORS问题和三个关键点强相关:
- 浏览器将
localhost和127.0.0.1视为完全不同的源,Keycloak和Gateway的跨域配置必须同时覆盖这两个地址 - 400错误本质是Keycloak收到的授权请求中,源地址或重定向URI不匹配客户端配置,触发参数校验失败
- Spring Cloud Gateway的CORS过滤器执行顺序可能晚于Security拦截器,导致配置不生效
具体解决步骤
1. 修正Keycloak客户端配置
- 打开Keycloak控制台,找到对应客户端的
Web Origins配置:- 直接填入
+(允许所有与Valid Redirect URIs匹配的源,本地开发最省心) - 或者明确添加:
http://localhost:8080、http://127.0.0.1:8080、http://localhost:8080/*、http://127.0.0.1:8080/*
- 直接填入
- 同步更新
Valid Redirect URIs,确保包含http://localhost:8080/*和http://127.0.0.1:8080/* - 注意:不要填
*,会和allowCredentials冲突,导致浏览器拒绝跨域请求
2. 调整Spring Cloud Gateway的CORS与Security配置
全局CORS配置必须整合到Security链中,确保CORS过滤器先于Security拦截执行:
@Configuration @EnableWebFluxSecurity public class GatewaySecurityConfig { @Bean public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) { http // 优先配置CORS .cors(cors -> cors.configurationSource(corsConfigurationSource())) .authorizeExchange(exchanges -> exchanges // 明确放行Swagger全路径 .pathMatchers("/webjars/**", "/swagger-ui/**", "/v3/api-docs/**", "/swagger-resources/**") .permitAll() .anyExchange().authenticated() ) .oauth2ResourceServer(oauth2 -> oauth2.jwt(Customizer.withDefaults())); return http.build(); } private CorsConfigurationSource corsConfigurationSource() { CorsConfiguration config = new CorsConfiguration(); // 允许本地两个源 config.addAllowedOrigin("http://localhost:8080"); config.addAllowedOrigin("http://127.0.0.1:8080"); // 允许所有请求方法 config.addAllowedMethod("*"); // 允许所有请求头(包括Keycloak授权头) config.addAllowedHeader("*"); // 允许携带凭证(Cookie、Authorization等) config.setAllowCredentials(true); // 暴露Swagger需要的响应头 config.addExposedHeader("Content-Type"); config.addExposedHeader("Authorization"); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", config); return source; } }
- 删掉之前独立的全局CORS配置类,避免冲突
3. 配置Swagger UI支持跨域凭证
Swagger UI发起请求时需要携带凭证,否则Keycloak会拒绝:
@Configuration public class SwaggerConfig { @Bean public OpenAPI customOpenAPI() { return new OpenAPI() .info(new Info().title("Gateway API").version("v1")); } @Bean public SwaggerUiConfigParameters swaggerUiConfigParameters() { SwaggerUiConfigParameters params = new SwaggerUiConfigParameters(); params.setTryItOutEnabled(true); // 开启携带凭证,解决跨域时的身份校验问题 params.setWithCredentials(true); return params; } }
4. 排查Docker Keycloak的网络问题
- 本地开发建议给Keycloak容器用
host网络模式,避免端口映射导致的源地址混淆:docker run -d --network host -e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN_PASSWORD=admin quay.io/keycloak/keycloak:latest start-dev - 如果用端口映射,确保Keycloak的
KEYCLOAK_FRONTEND_URL设置正确:docker run -d -p 8888:8080 -e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN_PASSWORD=admin -e KEYCLOAK_FRONTEND_URL=http://localhost:8888 quay.io/keycloak/keycloak:latest start-dev
5. 调试验证
- 重启Gateway和Keycloak
- 先访问
http://localhost:8080/v3/api-docs,查看响应头是否包含Access-Control-Allow-Origin: http://localhost:8080 - 打开浏览器开发者工具的
Network标签,查看Swagger UI发起的请求,确认没有CORS报错,且授权请求返回200
内容的提问来源于stack exchange,提问作者çagla boynueğri
相关产品推荐
相关产品推荐

