Keycloak + Spring Cloud Gateway + 认证授权
Posted
技术标签:
【中文标题】Keycloak + Spring Cloud Gateway + 认证授权【英文标题】:Keycloak + spring cloud gateway + authentication and authorization 【发布时间】:2021-11-20 17:43:37 【问题描述】:我正在尝试在 spring 云网关本身中使用 keycloak 进行身份验证和授权。但我收到以下错误。
Caused by: org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'springSecurityFilterChain' defined in class path resource [poc/apigateway/SecurityConfig.class]:
Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException:
Failed to instantiate [org.springframework.security.web.server.SecurityWebFilterChain]:
Factory method 'springSecurityFilterChain' threw exception; nested exception is java.lang.IllegalArgumentException:
clientRegistrationRepository cannot be null
我的应用程序.properties
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
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
keycloak.realm=microservice-realm
keycloak.resource=spring-cloud-gateway-client
keycloak.auth-server-url=http://localhost:8080/auth
keycloak.public-client=true
keycloak.securityConstraints[0].authRoles[0]=app-user
keycloak.securityConstraints[0].securityCollections[0].patterns[0]=/api/*
我的 build.gradle
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")
set('keycloakVersion', '4.8.3.Final')
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-security'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.security:spring-security-test'
// Keycloak
implementation 'org.keycloak:keycloak-spring-boot-starter'
dependencyManagement
imports
mavenBom "org.springframework.cloud:spring-cloud-dependencies:$springCloudVersion"
mavenBom "org.keycloak.bom:keycloak-adapter-bom:$keycloakVersion"
test
useJUnitPlatform()
我的 SecurityConfig.java
@Configuration
@EnableWebFluxSecurity
public class SecurityConfig
@Bean
public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http)
http.authorizeExchange(exchanges -> exchanges.anyExchange().authenticated())
.oauth2Login(withDefaults());
http.csrf().disable();
return http.build();
问题出现在应用程序启动时。我在这里要做的是在 API 网关本身中进行身份验证和基于角色的授权。
【问题讨论】:
【参考方案1】:Keycloak 适配器不适用于 WebFlux,只能用于 MVC,因此您应该删除此依赖项:
mavenBom "org.keycloak.bom:keycloak-adapter-bom:$keycloakVersion"
你可以使用
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>
并将 Keycloak 配置为 Oauth 服务器:
spring:
security:
oauth2:
client:
registration:
keycloak:
provider: keycloak
client-id: web
client-secret: 'cipherxxxx'
authorization-grant-type: authorization_code
redirect-uri: $keycloak-client.server-url/login/oauth2/code/keycloak
scope: openid
provider:
keycloak:
authorization-uri: $keycloak-client.server-url/realms/$keycloak-client.realm/protocol/openid-connect/auth
token-uri: $keycloak-client.server-url/realms/$keycloak-client.realm/protocol/openid-connect/token
user-info-uri: $keycloak-client.server-url/realms/$keycloak-client.realm/protocol/openid-connect/userinfo
jwk-set-uri: $keycloak-client.server-url/realms/$keycloak-client.realm/protocol/openid-connect/certs
user-name-attribute: name
user-info-authentication-method: header
resourceserver:
jwt:
jwk-set-uri: $keycloak-client.server-url/realms/$keycloak-client.realm/protocol/openid-connect/certs
keycloak-client:
server-url: https://keycloakURL/auth
realm: your-realm
还有过滤链:
@Bean
public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http)
http
.authorizeExchange()
.pathMatchers(constraintsConfig.getOpenUri())
.permitAll()
.and()
.authorizeExchange()
.anyExchange().authenticated()
.and()
.oauth2ResourceServer()
.jwt();
return http.build();
【讨论】:
以上是关于Keycloak + Spring Cloud Gateway + 认证授权的主要内容,如果未能解决你的问题,请参考以下文章
带有 keycloak 的 Spring Cloud 微服务
spring api gateway 不会将我重定向到 keycloak 提供的 spring-cloud-gateway-client url
尽管设置了承载令牌,但 Spring Cloud Gateway 重定向到 Keycloak 登录页面
如何使用 Keycloak 保护 Angular 8 前端和使用网关、eureka 的 Java Spring Cloud 微服务后端
spring-cloud-starter-consul-config 和 spring-cloud-consul-config 区别是什么?从网上没有搜到答案,待跟进。