java - Keycloak + Spring Cloud Gateway + 认证授权
问题描述
我正在尝试在 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
我的 application.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 网关本身中进行身份验证和基于角色的授权。
解决方案
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: '{cipher}xxxx'
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();
}
推荐阅读
- javascript - 如何在 2020 年像在 PHP 中一样简单地格式化 JavaScript 中的日期?
- python - hyperopt - 是否可以获得其搜索空间的当前值?
- sql - 尝试在 sql 中使用 YearFrac
- php - 有没有办法在 WordPress 中设置 add_menu_page() 的样式?
- ios - 在 SwiftUI 中滑动列表时隐藏导航栏
- css - 我无法更改块的颜色
- python - 管道中的第二个“ParallelRunStep”在启动时超时
- spring-batch - 即使作业失败,步骤/Tasklet 也始终执行
- reactjs - 是的,当条件不起作用时对对象进行验证
- xbee - 用于 SmartThings 集线器的 Zigbee 集群库命令