spring-未找到启动 ReactiveClientRegistrationRepository
spring-boot ReactiveClientRegistrationRepository not found
环境:Spring 启动 2.3.1,Java11
我已经尝试了一些东西(也与 spring 的示例应用程序进行了比较),但到目前为止,我未能成功创建需要 [=24] 的 WebClient
=].
启动我的 spring-boot 应用程序时出现以下异常:
required a bean of type 'org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository'
我理解的方式 spring-boot-autoconfigure 它应该使用 ReactiveOAuth2ClientAutoConfiguration
,因为在 yml 文件中给出了所需的属性。
根据一些代码片段,如果缺少某些内容,我可以提供更多内容以获取整个上下文
主要-Class
@Slf4j
@SpringBootApplication
@EnableConfigurationProperties(MyAppConfigurationProperties.class)
public class MyApp{
public static void main(final String[] args) {
SpringApplication.run(MyApp.class, args);
}
}
配置:
@Configuration
//@Import(ReactiveOAuth2ClientAutoConfiguration.class) // in the test it works with this, but should not be required: spring-boot-autoconfigure
public class MyRestClientConfig {
@Bean
WebClient myWebClient(WebClient.Builder builder, ReactiveClientRegistrationRepository clientRegistrations) {
//content not relevant to this problem
}
}
安全配置
@EnableGlobalMethodSecurity(securedEnabled = true)
@EnableWebSecurity
@EnableWebFluxSecurity
public class SecurityConfig {
}
application.yml
spring:
security:
oauth2:
client:
registration:
providerid:
authorization-grant-type: "client_credentials"
client-id: "myClientId"
client-secret: "mySecret"
user-info-authentication-method: header
provider:
providerid:
token-uri: "working token-uri"
我尝试了不同的依赖项,所以有些可能不需要。实际需要哪些依赖项?
pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<!-- <dependency>-->
<!-- <groupId>org.springframework.security.oauth.boot</groupId>-->
<!-- <artifactId>spring-security-oauth2-autoconfigure</artifactId>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>org.springframework.security.oauth</groupId>-->
<!-- <artifactId>spring-security-oauth2</artifactId>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-starter-oauth2-client</artifactId>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>org.springframework.security</groupId>-->
<!-- <artifactId>spring-security-oauth2-core</artifactId>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>org.springframework.security</groupId>-->
<!-- <artifactId>spring-security-oauth2-jose</artifactId>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-starter-webflux</artifactId>-->
<!-- </dependency>-->
在集成测试中 Spring-Boot-Application 启动
@EnableConfigurationProperties
@Import(ReactiveOAuth2ClientAutoConfiguration.class) // in the test it works with this, but should not be required: spring-boot-autoconfigure, can be omitted if added in MyRestClientConfig
@ComponentScan(basePackages = "com.mycompany")
public class ManualClientTester {
}
编辑 1:
自动配置的正匹配调试
在测试它在哪里工作:
============================
CONDITIONS EVALUATION REPORT
============================
Positive matches:
-----------------
ReactiveOAuth2ClientAutoConfiguration matched:
- @ConditionalOnClass found required classes 'reactor.core.publisher.Flux', 'org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity', 'org.springframework.security.oauth2.client.registration.ClientRegistration' (OnClassCondition)
- NoneNestedConditions 0 matched 1 did not; NestedCondition on ReactiveOAuth2ClientAutoConfiguration.NonServletApplicationCondition.ServletApplicationCondition not a servlet web application (ReactiveOAuth2ClientAutoConfiguration.NonServletApplicationCondition)
ReactiveOAuth2ClientConfigurations.ReactiveClientRegistrationRepositoryConfiguration matched:
- OAuth2 Clients Configured Condition found registered clients myClientId (ClientsConfiguredCondition)
- @ConditionalOnMissingBean (types: org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository; SearchStrategy: all) did not find any beans (OnBeanCondition)
ReactiveOAuth2ClientConfigurations.ReactiveOAuth2ClientConfiguration matched:
- @ConditionalOnBean (types: org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository; SearchStrategy: all) found bean 'clientRegistrationRepository' (OnBeanCondition)
ReactiveOAuth2ClientConfigurations.ReactiveOAuth2ClientConfiguration#authorizedClientRepository matched:
- @ConditionalOnMissingBean (types: org.springframework.security.oauth2.client.web.server.ServerOAuth2AuthorizedClientRepository; SearchStrategy: all) did not find any beans (OnBeanCondition)
ReactiveOAuth2ClientConfigurations.ReactiveOAuth2ClientConfiguration#authorizedClientService matched:
- @ConditionalOnMissingBean (types: org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizedClientService; SearchStrategy: all) did not find any beans (OnBeanCondition)
启动我的 spring 启动应用程序时:
============================
CONDITIONS EVALUATION REPORT
============================
Negative matches:
-----------------
ReactiveOAuth2ClientAutoConfiguration:
Did not match:
- NoneNestedConditions 1 matched 0 did not; NestedCondition on ReactiveOAuth2ClientAutoConfiguration.NonServletApplicationCondition.ServletApplicationCondition found 'session' scope (ReactiveOAuth2ClientAutoConfiguration.NonServletApplicationCondition)
Matched:
- @ConditionalOnClass found required classes 'reactor.core.publisher.Flux', 'org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity', 'org.springframework.security.oauth2.client.registration.ClientRegistration' (OnClassCondition)
编辑 2:
按照建议更改后,我现在有以下内容:
@EnableReactiveMethodSecurity
@EnableWebFluxSecurity
public class SecurityConfig {
}
pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
此外,spring-项目的所有使用版本:
<spring-amqp.version>2.2.7.RELEASE</spring-amqp.version>
<spring-batch.version>4.2.4.RELEASE</spring-batch.version>
<spring-boot.version>2.3.1.RELEASE</spring-boot.version>
<spring-data-releasetrain.version>Neumann-SR1</spring-data-releasetrain.version>
<spring-framework.version>5.2.7.RELEASE</spring-framework.version>
<spring-hateoas.version>1.1.0.RELEASE</spring-hateoas.version>
<spring-integration.version>5.3.1.RELEASE</spring-integration.version>
<spring-kafka.version>2.5.2.RELEASE</spring-kafka.version>
<spring-ldap.version>2.3.3.RELEASE</spring-ldap.version>
<spring-restdocs.version>2.0.4.RELEASE</spring-restdocs.version>
<spring-retry.version>1.2.5.RELEASE</spring-retry.version>
<spring-security.version>5.3.3.RELEASE</spring-security.version>
<spring-session-bom.version>Dragonfruit-RELEASE</spring-session-bom.version>
<spring-ws.version>3.0.9.RELEASE</spring-ws.version>
<spring.boot.version>2.3.1.RELEASE</spring.boot.version>
<spring.cloud.version>Hoxton.SR5</spring.cloud.version>
问题依然存在。
更新:
看起来“用户信息身份验证方法”(userInfoAuthenticationMethod
) 是 Provider
的 部分,而不是 Registration
.并且请也删除双引号。
spring:
security:
oauth2:
client:
registration:
providerid:
authorization-grant-type: client_credentials
client-id: myClientId
client-secret: mySecret
provider:
providerid:
token-uri: <working token-uri>
user-info-authentication-method: header
还有一个建议 - 为避免可能的冲突/不兼容的依赖项,请像这样使用 dependency management
并尝试拥有所有 spring 启动器。例如,spring 安全库是 spring-boot-starter-oauth2-client
和 spring-boot-starter-oauth2-resource-server
的一部分:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.3.1.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
只需这 2 个依赖项就可以完成工作:(这些是从 Gradle 文件中挑选的,请将它们更改为等效的 POM)
implementation 'org.springframework.boot:spring-boot-starter-webflux'
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
对于测试,您可能需要这个:
testImplementation 'org.springframework.security:spring-security-test:5.3.3.RELEASE'
你不应将两者混合:
@EnableWebSecurity
@EnableWebFluxSecurity
如果您的应用程序是响应式的,那么只需使用 @EnableWebFluxSecurity
。
来到 @EnableGlobalMethodSecurity(securedEnabled = true)
,这被描述为 here,建议 删除它并改用它:
@EnableReactiveMethodSecurity
我仍然对我的解决方案不满意,但我最终做了以下事情:
@Bean
public ReactiveClientRegistrationRepository reactiveClientRegistrationRepository(OAuth2ClientProperties oAuth2ClientProperties) {
List<ClientRegistration> clientRegistrations = new ArrayList<>();
// because autoconfigure does not work for an unknown reason, here the ClientRegistrations are manually configured based on the application.yml
oAuth2ClientProperties.getRegistration()
.forEach((k, v) -> {
String tokenUri = oAuth2ClientProperties.getProvider().get(k).getTokenUri();
ClientRegistration clientRegistration = ClientRegistration
.withRegistrationId(k)
.tokenUri(tokenUri)
.clientId(v.getClientId())
.clientSecret(v.getClientSecret())
.authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS)
.build();
clientRegistrations.add(clientRegistration);
});
return new InMemoryReactiveClientRegistrationRepository(clientRegistrations);
}
我将 spring-properties 用于 OAuth,然后根据这些属性创建 ReactiveClientRegistrationRepository
。
如果没有 stacktrace,很难提供相关答案。
似乎 Spring 启动无法从您的属性文件创建 ReactiveClientRegistrationRepository
。
尝试在您的客户端上添加提供商 属性。
oauth2:
client:
registration:
registrationId:
provider: providerId
client-id: clientId
client-secret: secret
authorization-grant-type: client_credentials
我 运行 遇到了同样的问题并注意到应用程序创建了 ClientRegistrationRepository
而不是 ReactiveClientRegistrationRepository
。在 Spring 启动的某处添加了 @EnableWebSecurity
(在这种情况下我们需要 @EnableWebFluxSecurity
)。
为了解决这个问题,我添加了以下 属性:
spring.main.web-application-type: reactive
如果您还使用 @SpringBootTest
来测试您的应用程序,您还需要在此处添加 属性。
@SpringBootTest(properties = ["spring.main.web-application-type=reactive]")
或将网络环境设置为NONE
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE)
发生这种情况的原因在这个答案中也有解释:
这样工作:
@Bean
public WebClient webClient(ClientRegistrationRepository clientRegistrationRepository) {
InMemoryReactiveClientRegistrationRepository registrationRepository = new InMemoryReactiveClientRegistrationRepository(clientRegistrationRepository.findByRegistrationId("REG_ID"));
InMemoryReactiveOAuth2AuthorizedClientService clientService = new InMemoryReactiveOAuth2AuthorizedClientService(registrationRepository);
AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager clientManager = new AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager(registrationRepository, clientService);
return WebClient.builder()
.baseUrl(BASEURL)
.filter(new ServerOAuth2AuthorizedClientExchangeFilterFunction(clientManager))
.build();
}
属性:
spring.security.oauth2.client.registration.REG_ID.client-id=CLIENT_ID
spring.security.oauth2.client.registration.REG_ID.client-name=CLIENT_NAME
spring.security.oauth2.client.registration.REG_ID.client-secret=SECRET
spring.security.oauth2.client.registration.REG_ID.authorization-grant-type=client_credentials
spring.security.oauth2.client.registration.REG_ID.scope=SCOPE
spring.security.oauth2.client.provider.REG_ID.issuer-uri=PATH_TO_.well-known/openid-configuration_SITE
编辑:
在return语句之前添加以下内容:
ServerOAuth2AuthorizedClientExchangeFilterFunction clientExchangeFilterFunction = new ServerOAuth2AuthorizedClientExchangeFilterFunction(clientManager);
clientExchangeFilterFunction.setDefaultClientRegistrationId("REG_ID");
并将return语句中的filter替换为:
.filter(clientExchangeFilterFunction)
ReactiveClientRepositoryRegistration Bean 需要明确定义。可以参考spring文档
https://docs.spring.io/spring-security/reference/reactive/oauth2/login/core.html#webflux-oauth2-login-register-reactiveclientregistrationrepository-bean
我通过编写这段代码解决了这个问题
@Bean("oauthWebClient")
WebClient webClient(ClientRegistrationRepository clientRegistrations) {
InMemoryReactiveClientRegistrationRepository registrationRepository = new InMemoryReactiveClientRegistrationRepository(
clientRegistrations.findByRegistrationId("reg-id"));
ServerOAuth2AuthorizedClientExchangeFilterFunction oauth =
new ServerOAuth2AuthorizedClientExchangeFilterFunction(
registrationRepository,
new UnAuthenticatedServerOAuth2AuthorizedClientRepository());
oauth.setDefaultClientRegistrationId("reg-id");
return WebClient.builder()
.filter(oauth)
.build();
}
环境:Spring 启动 2.3.1,Java11
我已经尝试了一些东西(也与 spring 的示例应用程序进行了比较),但到目前为止,我未能成功创建需要 [=24] 的 WebClient
=].
启动我的 spring-boot 应用程序时出现以下异常:
required a bean of type 'org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository'
我理解的方式 spring-boot-autoconfigure 它应该使用 ReactiveOAuth2ClientAutoConfiguration
,因为在 yml 文件中给出了所需的属性。
根据一些代码片段,如果缺少某些内容,我可以提供更多内容以获取整个上下文
主要-Class
@Slf4j
@SpringBootApplication
@EnableConfigurationProperties(MyAppConfigurationProperties.class)
public class MyApp{
public static void main(final String[] args) {
SpringApplication.run(MyApp.class, args);
}
}
配置:
@Configuration
//@Import(ReactiveOAuth2ClientAutoConfiguration.class) // in the test it works with this, but should not be required: spring-boot-autoconfigure
public class MyRestClientConfig {
@Bean
WebClient myWebClient(WebClient.Builder builder, ReactiveClientRegistrationRepository clientRegistrations) {
//content not relevant to this problem
}
}
安全配置
@EnableGlobalMethodSecurity(securedEnabled = true)
@EnableWebSecurity
@EnableWebFluxSecurity
public class SecurityConfig {
}
application.yml
spring:
security:
oauth2:
client:
registration:
providerid:
authorization-grant-type: "client_credentials"
client-id: "myClientId"
client-secret: "mySecret"
user-info-authentication-method: header
provider:
providerid:
token-uri: "working token-uri"
我尝试了不同的依赖项,所以有些可能不需要。实际需要哪些依赖项?
pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<!-- <dependency>-->
<!-- <groupId>org.springframework.security.oauth.boot</groupId>-->
<!-- <artifactId>spring-security-oauth2-autoconfigure</artifactId>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>org.springframework.security.oauth</groupId>-->
<!-- <artifactId>spring-security-oauth2</artifactId>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-starter-oauth2-client</artifactId>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>org.springframework.security</groupId>-->
<!-- <artifactId>spring-security-oauth2-core</artifactId>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>org.springframework.security</groupId>-->
<!-- <artifactId>spring-security-oauth2-jose</artifactId>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-starter-webflux</artifactId>-->
<!-- </dependency>-->
在集成测试中 Spring-Boot-Application 启动
@EnableConfigurationProperties
@Import(ReactiveOAuth2ClientAutoConfiguration.class) // in the test it works with this, but should not be required: spring-boot-autoconfigure, can be omitted if added in MyRestClientConfig
@ComponentScan(basePackages = "com.mycompany")
public class ManualClientTester {
}
编辑 1: 自动配置的正匹配调试
在测试它在哪里工作:
============================
CONDITIONS EVALUATION REPORT
============================
Positive matches:
-----------------
ReactiveOAuth2ClientAutoConfiguration matched:
- @ConditionalOnClass found required classes 'reactor.core.publisher.Flux', 'org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity', 'org.springframework.security.oauth2.client.registration.ClientRegistration' (OnClassCondition)
- NoneNestedConditions 0 matched 1 did not; NestedCondition on ReactiveOAuth2ClientAutoConfiguration.NonServletApplicationCondition.ServletApplicationCondition not a servlet web application (ReactiveOAuth2ClientAutoConfiguration.NonServletApplicationCondition)
ReactiveOAuth2ClientConfigurations.ReactiveClientRegistrationRepositoryConfiguration matched:
- OAuth2 Clients Configured Condition found registered clients myClientId (ClientsConfiguredCondition)
- @ConditionalOnMissingBean (types: org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository; SearchStrategy: all) did not find any beans (OnBeanCondition)
ReactiveOAuth2ClientConfigurations.ReactiveOAuth2ClientConfiguration matched:
- @ConditionalOnBean (types: org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository; SearchStrategy: all) found bean 'clientRegistrationRepository' (OnBeanCondition)
ReactiveOAuth2ClientConfigurations.ReactiveOAuth2ClientConfiguration#authorizedClientRepository matched:
- @ConditionalOnMissingBean (types: org.springframework.security.oauth2.client.web.server.ServerOAuth2AuthorizedClientRepository; SearchStrategy: all) did not find any beans (OnBeanCondition)
ReactiveOAuth2ClientConfigurations.ReactiveOAuth2ClientConfiguration#authorizedClientService matched:
- @ConditionalOnMissingBean (types: org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizedClientService; SearchStrategy: all) did not find any beans (OnBeanCondition)
启动我的 spring 启动应用程序时:
============================
CONDITIONS EVALUATION REPORT
============================
Negative matches:
-----------------
ReactiveOAuth2ClientAutoConfiguration:
Did not match:
- NoneNestedConditions 1 matched 0 did not; NestedCondition on ReactiveOAuth2ClientAutoConfiguration.NonServletApplicationCondition.ServletApplicationCondition found 'session' scope (ReactiveOAuth2ClientAutoConfiguration.NonServletApplicationCondition)
Matched:
- @ConditionalOnClass found required classes 'reactor.core.publisher.Flux', 'org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity', 'org.springframework.security.oauth2.client.registration.ClientRegistration' (OnClassCondition)
编辑 2: 按照建议更改后,我现在有以下内容:
@EnableReactiveMethodSecurity
@EnableWebFluxSecurity
public class SecurityConfig {
}
pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
此外,spring-项目的所有使用版本:
<spring-amqp.version>2.2.7.RELEASE</spring-amqp.version>
<spring-batch.version>4.2.4.RELEASE</spring-batch.version>
<spring-boot.version>2.3.1.RELEASE</spring-boot.version>
<spring-data-releasetrain.version>Neumann-SR1</spring-data-releasetrain.version>
<spring-framework.version>5.2.7.RELEASE</spring-framework.version>
<spring-hateoas.version>1.1.0.RELEASE</spring-hateoas.version>
<spring-integration.version>5.3.1.RELEASE</spring-integration.version>
<spring-kafka.version>2.5.2.RELEASE</spring-kafka.version>
<spring-ldap.version>2.3.3.RELEASE</spring-ldap.version>
<spring-restdocs.version>2.0.4.RELEASE</spring-restdocs.version>
<spring-retry.version>1.2.5.RELEASE</spring-retry.version>
<spring-security.version>5.3.3.RELEASE</spring-security.version>
<spring-session-bom.version>Dragonfruit-RELEASE</spring-session-bom.version>
<spring-ws.version>3.0.9.RELEASE</spring-ws.version>
<spring.boot.version>2.3.1.RELEASE</spring.boot.version>
<spring.cloud.version>Hoxton.SR5</spring.cloud.version>
问题依然存在。
更新:
看起来“用户信息身份验证方法”(userInfoAuthenticationMethod
) 是 Provider
的 部分,而不是 Registration
.并且请也删除双引号。
spring:
security:
oauth2:
client:
registration:
providerid:
authorization-grant-type: client_credentials
client-id: myClientId
client-secret: mySecret
provider:
providerid:
token-uri: <working token-uri>
user-info-authentication-method: header
还有一个建议 - 为避免可能的冲突/不兼容的依赖项,请像这样使用 dependency management
并尝试拥有所有 spring 启动器。例如,spring 安全库是 spring-boot-starter-oauth2-client
和 spring-boot-starter-oauth2-resource-server
的一部分:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.3.1.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
只需这 2 个依赖项就可以完成工作:(这些是从 Gradle 文件中挑选的,请将它们更改为等效的 POM)
implementation 'org.springframework.boot:spring-boot-starter-webflux'
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
对于测试,您可能需要这个:
testImplementation 'org.springframework.security:spring-security-test:5.3.3.RELEASE'
你不应将两者混合:
@EnableWebSecurity
@EnableWebFluxSecurity
如果您的应用程序是响应式的,那么只需使用 @EnableWebFluxSecurity
。
来到 @EnableGlobalMethodSecurity(securedEnabled = true)
,这被描述为 here,建议 删除它并改用它:
@EnableReactiveMethodSecurity
我仍然对我的解决方案不满意,但我最终做了以下事情:
@Bean
public ReactiveClientRegistrationRepository reactiveClientRegistrationRepository(OAuth2ClientProperties oAuth2ClientProperties) {
List<ClientRegistration> clientRegistrations = new ArrayList<>();
// because autoconfigure does not work for an unknown reason, here the ClientRegistrations are manually configured based on the application.yml
oAuth2ClientProperties.getRegistration()
.forEach((k, v) -> {
String tokenUri = oAuth2ClientProperties.getProvider().get(k).getTokenUri();
ClientRegistration clientRegistration = ClientRegistration
.withRegistrationId(k)
.tokenUri(tokenUri)
.clientId(v.getClientId())
.clientSecret(v.getClientSecret())
.authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS)
.build();
clientRegistrations.add(clientRegistration);
});
return new InMemoryReactiveClientRegistrationRepository(clientRegistrations);
}
我将 spring-properties 用于 OAuth,然后根据这些属性创建 ReactiveClientRegistrationRepository
。
如果没有 stacktrace,很难提供相关答案。
似乎 Spring 启动无法从您的属性文件创建 ReactiveClientRegistrationRepository
。
尝试在您的客户端上添加提供商 属性。
oauth2:
client:
registration:
registrationId:
provider: providerId
client-id: clientId
client-secret: secret
authorization-grant-type: client_credentials
我 运行 遇到了同样的问题并注意到应用程序创建了 ClientRegistrationRepository
而不是 ReactiveClientRegistrationRepository
。在 Spring 启动的某处添加了 @EnableWebSecurity
(在这种情况下我们需要 @EnableWebFluxSecurity
)。
为了解决这个问题,我添加了以下 属性:
spring.main.web-application-type: reactive
如果您还使用 @SpringBootTest
来测试您的应用程序,您还需要在此处添加 属性。
@SpringBootTest(properties = ["spring.main.web-application-type=reactive]")
或将网络环境设置为NONE
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE)
发生这种情况的原因在这个答案中也有解释:
这样工作:
@Bean
public WebClient webClient(ClientRegistrationRepository clientRegistrationRepository) {
InMemoryReactiveClientRegistrationRepository registrationRepository = new InMemoryReactiveClientRegistrationRepository(clientRegistrationRepository.findByRegistrationId("REG_ID"));
InMemoryReactiveOAuth2AuthorizedClientService clientService = new InMemoryReactiveOAuth2AuthorizedClientService(registrationRepository);
AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager clientManager = new AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager(registrationRepository, clientService);
return WebClient.builder()
.baseUrl(BASEURL)
.filter(new ServerOAuth2AuthorizedClientExchangeFilterFunction(clientManager))
.build();
}
属性:
spring.security.oauth2.client.registration.REG_ID.client-id=CLIENT_ID
spring.security.oauth2.client.registration.REG_ID.client-name=CLIENT_NAME
spring.security.oauth2.client.registration.REG_ID.client-secret=SECRET
spring.security.oauth2.client.registration.REG_ID.authorization-grant-type=client_credentials
spring.security.oauth2.client.registration.REG_ID.scope=SCOPE
spring.security.oauth2.client.provider.REG_ID.issuer-uri=PATH_TO_.well-known/openid-configuration_SITE
编辑:
在return语句之前添加以下内容:
ServerOAuth2AuthorizedClientExchangeFilterFunction clientExchangeFilterFunction = new ServerOAuth2AuthorizedClientExchangeFilterFunction(clientManager);
clientExchangeFilterFunction.setDefaultClientRegistrationId("REG_ID");
并将return语句中的filter替换为:
.filter(clientExchangeFilterFunction)
ReactiveClientRepositoryRegistration Bean 需要明确定义。可以参考spring文档 https://docs.spring.io/spring-security/reference/reactive/oauth2/login/core.html#webflux-oauth2-login-register-reactiveclientregistrationrepository-bean
我通过编写这段代码解决了这个问题
@Bean("oauthWebClient")
WebClient webClient(ClientRegistrationRepository clientRegistrations) {
InMemoryReactiveClientRegistrationRepository registrationRepository = new InMemoryReactiveClientRegistrationRepository(
clientRegistrations.findByRegistrationId("reg-id"));
ServerOAuth2AuthorizedClientExchangeFilterFunction oauth =
new ServerOAuth2AuthorizedClientExchangeFilterFunction(
registrationRepository,
new UnAuthenticatedServerOAuth2AuthorizedClientRepository());
oauth.setDefaultClientRegistrationId("reg-id");
return WebClient.builder()
.filter(oauth)
.build();
}