如何在Kubernetes中配置Keycloak?容器化Spring应用授权异常排查
Spring Cloud网关容器化后无法连接Keycloak的解决方法
核心问题分析
报错Unable to resolve the Configuration with the provided Issuer本质是两个问题:
- Spring Boot容器无法通过配置的
keycloak-server主机名访问到Keycloak容器 - Keycloak生成的JWT中的
iss字段与Spring Boot配置的issuer-uri不一致,导致校验失败
一、确保容器网络互通
Docker Compose场景
将Spring Boot网关和Keycloak加入同一个自定义网络,容器间才能通过名称互相访问:
networks: keycloak-net: driver: bridge services: keycloak-server: image: quay.io/keycloak/keycloak:22.0.3 container_name: keycloak-server networks: - keycloak-net environment: - KEYCLOAK_ADMIN=admin - KEYCLOAK_ADMIN_PASSWORD=admin command: start-dev ports: - "8080:8080" spring-gateway: build: ./gateway container_name: spring-gateway networks: - keycloak-net ports: - "9000:9000"
Kubernetes场景
- 确保Keycloak的Service名称为
keycloak-server,且与Spring Boot网关处于同一Namespace - 若跨Namespace,需将
issuer-uri改为http://keycloak-server.<namespace>.svc.cluster.local:8080/realms/master
二、统一Issuer配置(关键)
Keycloak默认会根据请求地址生成JWT的iss字段,必须让这个值和Spring Boot配置的issuer-uri完全一致:
Keycloak端配置
启动时指定主机名,确保生成的JWT issuer地址为容器内部可访问的地址:
# Docker Compose中的Keycloak环境变量 environment: - KEYCLOAK_ADMIN=admin - KEYCLOAK_ADMIN_PASSWORD=admin - KC_HOSTNAME=keycloak-server - KC_HTTP_PORT=8080 - KC_HOSTNAME_STRICT=false # 关闭严格主机名校验(开发环境) - KC_HOSTNAME_STRICT_HTTPS=false # HTTP模式下关闭HTTPS校验
Spring Boot端配置
在application.yml中指定匹配的issuer-uri:
spring: security: oauth2: resourceserver: jwt: issuer-uri: http://keycloak-server:8080/realms/master
三、开发环境临时绕过SSL校验(可选)
若使用HTTPS且Keycloak用自签名证书,Spring Boot容器会因证书信任问题解析失败,可自定义JwtDecoder跳过校验:
@Configuration public class JwtConfig { @Value("${spring.security.oauth2.resourceserver.jwt.issuer-uri}") private String issuerUri; @Bean public JwtDecoder jwtDecoder() throws Exception { // 构建信任所有证书的SSL上下文 SSLContext sslContext = SSLContexts.custom() .loadTrustMaterial(null, (chain, authType) -> true) .build(); // 配置HttpClient跳过证书校验 HttpClient httpClient = HttpClients.custom() .setSSLContext(sslContext) .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE) .build(); ClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(httpClient); // 获取Keycloak的OIDC元数据 OAuth2AuthorizationServerMetadata metadata = new DefaultAuthorizationServerMetadataResolver(requestFactory) .resolve(URI.create(issuerUri + "/.well-known/openid-configuration")); // 自定义JwtDecoder NimbusJwtDecoder jwtDecoder = NimbusJwtDecoder.withJwkSetUri(metadata.getJwkSetUri()) .jwtProcessorCustomizer(processor -> { OAuth2TokenValidator<Jwt> issuerValidator = JwtValidators.createDefaultWithIssuer(issuerUri); processor.setJwtValidator(issuerValidator); }) .build(); return jwtDecoder; } }
注意:生产环境必须配置合法的SSL证书,禁止使用此方法。
内容的提问来源于stack exchange,提问作者Dhananjay
相关产品推荐
相关产品推荐

