Spring Cloud Gateway集成Keycloak鉴权启动报clientRegistrationRepository为空错误
异常原因
报错clientRegistrationRepository cannot be null的核心诱因是依赖冲突与配置冗余,具体如下:
- 你引入的
keycloak-spring-boot-starter是Keycloak官方针对Servlet栈Spring Boot应用开发的适配器,完全不兼容Spring Cloud Gateway底层使用的WebFlux响应式栈,会破坏Spring Security OAuth2客户端的自动装配逻辑,导致ClientRegistrationRepositoryBean无法正常创建。 - 项目中同时配置了Spring Security OAuth2客户端、OAuth2资源服务器、Keycloak原生适配器三类鉴权配置,配置逻辑冲突进一步阻断了自动装配流程。
application.properties中scope配置项存在多余空格,会导致scope解析异常,也可能触发配置加载失败。
修复方案
步骤1:清理冲突依赖
修改build.gradle,移除Keycloak官方适配器相关的依赖与BOM配置,Spring Security 5+已原生支持Keycloak作为OAuth2认证源,无需额外引入适配器:
plugins { id 'org.springframework.boot' version '2.5.4' id 'io.spring.dependency-management' version '1.0.11.RELEASE' id 'java' } group = 'poc' version = '0.0.1-SNAPSHOT' sourceCompatibility = '1.8' repositories { mavenCentral() } ext { set('springCloudVersion', "2020.0.3") } dependencies { implementation 'org.springframework.cloud:spring-cloud-starter-gateway' implementation 'org.springframework.boot:spring-boot-starter-oauth2-client' implementation 'org.springframework.boot:spring-boot-starter-oauth2-resource-server' implementation 'org.springframework.boot:spring-boot-starter-security' testImplementation 'org.springframework.boot:spring-boot-starter-test' testImplementation 'org.springframework.security:spring-security-test' } dependencyManagement { imports { mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}" } } test { useJUnitPlatform() }
步骤2:清理冗余配置
删除application.properties中所有keycloak.开头的原生适配器配置,同时修正scope配置的多余空格:
spring.application.name=api-gateway spring.cloud.gateway.default-filters=TokenRelay spring.cloud.gateway.routes[0].id=product-service spring.cloud.gateway.routes[0].uri=http://localhost:8009 spring.cloud.gateway.routes[0].predicates[0]=Path=/api/product spring.cloud.gateway.routes[1].id=order-service spring.cloud.gateway.routes[1].uri=http://localhost:8008 spring.cloud.gateway.routes[1].predicates[0]=Path=/api/order spring.security.oauth2.client.provider.keycloak.issuer-uri=http://localhost:8080/auth/realms/microservice-realm spring.security.oauth2.client.registration.spring-cloud-gateway-client.client-id=spring-cloud-gateway-client spring.security.oauth2.client.registration.spring-cloud-gateway-client.client-secret=d1b3670c-f1c3-480c-9cda-8e107aec7d5b # 移除scope值中的多余空格 spring.security.oauth2.client.registration.spring-cloud-gateway-client.scope=openid,profile,roles spring.security.oauth2.client.registration.spring-cloud-gateway-client.authorization-grant-type=authorization_code spring.security.oauth2.client.registration.spring-cloud-gateway-client.redirect-uri=http://localhost:8005/login/oauth2/code/spring-cloud-gateway-client spring.security.oauth2.resourceserver.jwt.issuer-uri=http://localhost:8080/auth/realms/microservice-realm
步骤3:修正安全配置类
适配WebFlux栈的安全规则,同时兼容OAuth2登录与JWT资源校验逻辑:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity; import org.springframework.security.config.web.server.ServerHttpSecurity; import org.springframework.security.web.server.SecurityWebFilterChain; import static org.springframework.security.config.Customizer.withDefaults; @Configuration @EnableWebFluxSecurity public class SecurityConfig { @Bean public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) { http.authorizeExchange(exchanges -> exchanges.anyExchange().authenticated()) // 支持OAuth2授权码登录 .oauth2Login(withDefaults()) // 支持JWT令牌校验(适配前端直接传令牌的场景) .oauth2ResourceServer(oauth2 -> oauth2.jwt(withDefaults())); http.csrf().disable(); return http.build(); } }
验证逻辑
应用启动成功后,访问任意/api/*路径会自动跳转至Keycloak登录页,登录完成后将自动回调网关并转发请求到下游服务,TokenRelay过滤器会自动将用户访问令牌携带到下游服务的请求头中。
内容的提问来源于stack exchange,提问作者Chatura Mohotti
相关产品推荐
相关产品推荐

