【问题标题】:spring-boot ReactiveClientRegistrationRepository not foundspring-boot ReactiveClientRegistrationRepository 找不到
【发布时间】:2020-11-11 16:42:15
【问题描述】:

环境:Spring Boot 2.3.1,Java 11

我已经尝试了一些东西(也与 spring 的示例应用程序进行比较),但到目前为止,我未能成功创建需要 ReactiveClientRegistrationRepositoryWebClient

启动我的 spring-boot 应用程序时出现以下异常:

required a bean of type 'org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository'

我理解 spring-boot-autoconfigure 的方式应该使用ReactiveOAuth2ClientAutoConfiguration,因为在 yml 文件中给出了所需的属性。

按照一些 code-sn-ps,如果缺少某些内容,我可以提供更多以获取整个上下文

主类

@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 Boot 应用程序时:

============================
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-projects 版本:

    <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>

问题依然存在。

【问题讨论】:

    标签: java spring-boot spring-webclient spring-reactive


    【解决方案1】:

    更新:

    看起来“user-info-authentication-method”(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 Boot 启动器。例如 spring 安全库是 spring-boot-starter-oauth2-clientspring-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>
    

    这两个依赖项应该可以工作:(这些是从 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
    

    【讨论】:

    • 我删除了与 oauth2 相关的所有依赖项,现在只使用这三个 spring-boot-starter-webflux、spring-boot-starter-security 和 spring-security-oauth2-client 此外我删除了@987654337 @注解。问题依然存在。
    • @marco 你也删除了EnableGlobalMethodSecurity 注释吗?并且不要使用spring-boot-starter-security。安全库将附带spring-security-oauth2-client。如果你的应用也是资源服务器,那么你需要spring-boot-starter-oauth2-resource-server
    • 我现在又做了两个,但我仍然得到同样的错误。我也认为我需要 org.springframework.security.core.userdetails.UserDetailsS​​ervice 的 spring-boot-starter-security
    • 没有@marco spring-boot-starter-oauth2-client 包含spring-security-core
    • 在您完成所有这些更改后分享您的代码。如果您认为您的问题变得非常大,请使用friendpaste.com 或 github gists 或其他工具
    【解决方案2】:

    我仍然对我的解决方案不满意,但我最终做了以下事情:

        @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

    【讨论】:

    • 上述来自 Jelle van Es 的回答实际上是正确的,我最初也是走 ReactiveClientRegistrationRepository 路线的,然后在我开始使用 CORS 和 CSRF 时就陷入了整个世界的伤害。
    【解决方案3】:

    如果没有 stacktrace,很难提供相关答案。

    似乎 Spring boot 无法从您的属性文件中创建 ReactiveClientRegistrationRepository

    尝试在您的客户端上添加提供者属性。

    oauth2:
      client:
        registration:
          registrationId:
            provider: providerId
            client-id: clientId
            client-secret: secret
            authorization-grant-type: client_credentials
    

    【讨论】:

      【解决方案4】:

      我遇到了同样的问题,并注意到应用程序创建了 ClientRegistrationRepository 而不是 ReactiveClientRegistrationRepository。在 Spring boot 的某个地方添加了@EnableWebSecurity(在这种情况下我们需要@EnableWebFluxSecurity)。

      为了解决这个问题,我添加了以下属性:

      spring.main.web-application-type: reactive

      如果您还使用@SpringBootTest 来测试您的应用程序,您还需要在此处添加属性。

      @SpringBootTest(properties = ["spring.main.web-application-type=reactive]")
      

      或者通过将网络环境设置为NONE

      @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE)
      

      这个答案中也解释了发生这种情况的原因:Error when using @EnableWebFluxSecurity in springboot

      【讨论】:

        【解决方案5】:

        这样工作:

        @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)
        

        【讨论】:

          猜你喜欢
          • 2020-08-31
          • 2020-07-31
          • 2017-10-11
          • 2021-03-14
          • 2017-06-28
          • 1970-01-01
          • 1970-01-01
          • 2022-11-10
          • 2018-12-13
          相关资源
          最近更新 更多