programing

'org. 스프링 프레임워크' 유형의 콩을 정의하는 것을 고려합니다.security.oauth2.client.registration.사용자 구성의 '반응형 클라이언트 등록 리포지토리'

linuxpc 2023. 7. 15. 09:45
반응형

'org. 스프링 프레임워크' 유형의 콩을 정의하는 것을 고려합니다.security.oauth2.client.registration.사용자 구성의 '반응형 클라이언트 등록 리포지토리'

현재 Spring OAuth2 Client 버전을 사용하고 있습니다.5.2.4.RELEASE내 프로젝트에서.

저는 여기 공식 스프링 문서를 참조하여 스프링 보안을 구현했습니다.

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository;
import org.springframework.security.oauth2.client.web.reactive.function.client.ServerOAuth2AuthorizedClientExchangeFilterFunction;
import org.springframework.security.oauth2.client.web.server.ServerOAuth2AuthorizedClientRepository;
import org.springframework.web.reactive.function.client.ExchangeFilterFunction;
import org.springframework.web.reactive.function.client.WebClient;

import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import reactor.core.publisher.Mono;

@AllArgsConstructor
@Configuration
@Slf4j
public class WebClientConfig {

    @Bean("AuthProvider")
    WebClient webClient(ReactiveClientRegistrationRepository clientRegistrations, ServerOAuth2AuthorizedClientRepository authorizedClients) {
        ServerOAuth2AuthorizedClientExchangeFilterFunction oauth = new ServerOAuth2AuthorizedClientExchangeFilterFunction(
                clientRegistrations,
                authorizedClients);
        oauth.setDefaultOAuth2AuthorizedClient(true);
        oauth.setDefaultClientRegistrationId("AuthProvider");
        return WebClient.builder()
                .filter(oauth)
                .filter(this.logRequest())
                .build();
    }

    
    private ExchangeFilterFunction logRequest() {
        return ExchangeFilterFunction.ofRequestProcessor(clientRequest -> {
            log.info("Request: [{}] {}", clientRequest.method(), clientRequest.url());
            log.debug("Payload: {}", clientRequest.body());
            return Mono.just(clientRequest);
        });
    }

application.svl

   security:
    oauth2:
      client:
        provider:
          AuthProvider:
            token-uri: ${tokenpath<read from environment variable>}
        registration:
          AuthProvider:
            authorization-grant-type: client_credentials
            client-id: ${<read from environment variable>}
            client-secret: ${<read from environment variable>}

응용 프로그램 시작 시 다음 오류가 발생합니다.

***************************
APPLICATION FAILED TO START
***************************

Description:

Parameter 0 of method webClient in com.sample.config.WebClientConfig required a bean of type 'org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository' that could not be found.

The injection point has the following annotations:
    - @org.springframework.beans.factory.annotation.Autowired(required=true)


Action:

Consider defining a bean of type 'org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository' in your configuration.

제가 누락된 구성이 있으면 지적해 주십시오.또한 저는 다른 StackOverflow 질문들로부터 많은 도움을 받지 못했습니다.

스프링 부트 구성이 완벽합니다.


문제의 근본 원인:application.yaml에 문제가 있습니다.구성이 잘못되었거나 환경에서 선택되지 않았습니다.

따라서 문제는 OAuth2 버전이 아니라 application.yaml의 구성입니다.

참고: ReactiveClientRegistrationRepository빈은 OAuth2 응용 프로그램 소유자 세부 정보로 클라이언트를 구성할 때만 생성됩니다.


저는 start.spring.io 에서 새로운 프로젝트를 만들고 거기에 당신의 구성을 사용했습니다.

그리고 당신의 구성으로 프로젝트를 실행한 후, 저는 같은 문제에 직면했습니다.

오류 로그:

***************************
APPLICATION FAILED TO START
***************************

Description:

Parameter 0 of method webClient in com.example.sampleoauth2.WebClientConfig required a bean of type 'org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository' that could not be found.

The following candidates were found but could not be injected:
    - Bean method 'clientRegistrationRepository' in 'ReactiveOAuth2ClientConfigurations.ReactiveClientRegistrationRepositoryConfiguration' not loaded because OAuth2 Clients Configured Condition registered clients is not available


Action:

Consider revisiting the entries above or defining a bean of type 'org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository' in your configuration.

그리고 application.yml 파일에서 속성을 구성하지 않은 것을 확인했습니다.

스프링 부트 앱을 OAuth 앱으로 등록할 때 github에서 client-id 및 client-secret를 가져오는 방법에 대해 Spring BootOAuth 2.0 Docs를 읽었습니다.

애플리케이션이 작동하기 시작하자 마자 구성했습니다.


spring-boot 2.3.1.REASE 및 OAuth2Client 버전 5.3.3을 사용하고 있습니다.

My pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.1.RELEASE</version>
        <relativePath /> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>sampleOauth2</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>sampleOauth2</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <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>
        <dependency>
            <groupId>org.projectreactor</groupId>
            <artifactId>reactor-spring</artifactId>
            <version>1.0.1.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

클라이언트가 application.yml에 대한 허브 등록 속성을 가져옵니다.

spring:
  security:
    oauth2:
      client:
        registration:
          github:
            client-id: 22a7100de41c7308d346
            client-secret: 05910ab890be29579e9c183443d92e756c450aaf

업데이트된 WebClientConfig @Configuration 클래스:

package com.example.sampleoauth2;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository;
import org.springframework.security.oauth2.client.web.reactive.function.client.ServerOAuth2AuthorizedClientExchangeFilterFunction;
import org.springframework.security.oauth2.client.web.server.ServerOAuth2AuthorizedClientRepository;
import org.springframework.web.reactive.function.client.ExchangeFilterFunction;
import org.springframework.web.reactive.function.client.WebClient;

import reactor.core.publisher.Mono;

@Configuration
public class WebClientConfig {

    public static Logger log = LogManager.getLogger();

    @Bean
    public WebClient webClient(ReactiveClientRegistrationRepository clientRegistrations,
            ServerOAuth2AuthorizedClientRepository authorizedClients) {
        ServerOAuth2AuthorizedClientExchangeFilterFunction oauth = new ServerOAuth2AuthorizedClientExchangeFilterFunction(
                clientRegistrations, authorizedClients);
        oauth.setDefaultOAuth2AuthorizedClient(true);
        return WebClient.builder().filter(oauth).filter(this.logRequest()).build();
    }

    private ExchangeFilterFunction logRequest() {
        return ExchangeFilterFunction.ofRequestProcessor(clientRequest -> {
            log.info("Request: [{}] {}", clientRequest.method(), clientRequest.url());
            log.debug("Payload: {}", clientRequest.body());
            return Mono.just(clientRequest);
        });
    }
}

성공 로그:

   .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.3.1.RELEASE)

2020-06-26 20:36:08.380  INFO 15956 --- [           main] c.e.s.SampleOauth2Application            : Starting SampleOauth2Application on Anishs-MacBook-Pro.local with PID 15956 (/Users/anish/Downloads/sampleOauth2/target/classes started by anish in /Users/anish/Downloads/sampleOauth2)
2020-06-26 20:36:08.381  INFO 15956 --- [           main] c.e.s.SampleOauth2Application            : No active profile set, falling back to default profiles: default
2020-06-26 20:36:08.935  INFO 15956 --- [           main] ctiveUserDetailsServiceAutoConfiguration : 

Using generated security password: 7c63302f-f913-4aa1-852d-cb8445719acb

2020-06-26 20:36:09.132  INFO 15956 --- [           main] o.s.b.web.embedded.netty.NettyWebServer  : Netty started on port(s): 8080
2020-06-26 20:36:09.138  INFO 15956 --- [           main] c.e.s.SampleOauth2Application            : Started SampleOauth2Application in 0.978 seconds (JVM running for 1.313)

나는 스프링 부트 2.3.1을 사용하고 있습니다. 릴리스 나는 같은 문제를 가지고 있었습니다. 내 pom.xml은 내 pom.xml에 이러한 종속성을 모두 포함하고 있었습니다.

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-webflux</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

저는 다음과 같은 종속성을 제거했고 그것이 저에게 도움이 되었습니다.

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

이렇게 말하면 번거로움이 해결되지 않지만 종속성 충돌 문제가 될 수도 있습니다.

이 게시물은 저를 정상 궤도에 올려놓았습니다. Spring Security 5.3.2 ReactiveClientRegistrationRepository bean을 찾을 수 없습니다.

저는 @AnishB 구성을 사용했습니다.답변으로 제안되었지만 여전히 오류가 발생했습니다.

Parameter 0 of method webClient in com.example.sampleoauth2.WebClientConfig required a bean of type 'org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository' that could not be found.

그래서 저는 스프링 2.3.1에 이러한 종속성을 사용해야 했습니다.릴리스:

<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-oauth2-client</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-webflux</artifactId>
</dependency>

은 그고이것은입니다.WebClientConfig 명령어:

@Configuration
public class WebClientConfig {

    private static final Logger log = LoggerFactory.getLogger(WebClientConfig.class);

    @Bean("cr")
    ReactiveClientRegistrationRepository getRegistration(
            @Value("${spring.security.oauth2.client.provider.keycloak.token-uri}") String tokenUri,
            @Value("${spring.security.oauth2.client.registration.keycloak.client-id}") String clientId,
            @Value("${spring.security.oauth2.client.registration.keycloak.client-secret}") String clientSecret
    ) {
        ClientRegistration registration = ClientRegistration
                .withRegistrationId("keycloak")
                .tokenUri(tokenUri)
                .clientId(clientId)
                .clientSecret(clientSecret)
                .authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS)
                .build();
        return new InMemoryReactiveClientRegistrationRepository(registration);
    }

    @Bean(name = "keycloak")
    WebClient webClient(@Qualifier("cr") ReactiveClientRegistrationRepository clientRegistrations) {
        ServerOAuth2AuthorizedClientExchangeFilterFunction oauth = new ServerOAuth2AuthorizedClientExchangeFilterFunction(clientRegistrations, new UnAuthenticatedServerOAuth2AuthorizedClientRepository());
        oauth.setDefaultClientRegistrationId("keycloak");
        return WebClient.builder()
                .filter(oauth)
                .filter(logRequest())
                .build();
    }

    private ExchangeFilterFunction logRequest() {
        return ExchangeFilterFunction.ofRequestProcessor(clientRequest -> {
            log.info("Request: [{}] {}", clientRequest.method(), clientRequest.url());
            log.debug("Payload: {}", clientRequest.body());

            return Mono.just(clientRequest);
        });
    }
}

그리고 모든 것이 잘 작동하지만, 왜 @AnishB.의 해결책이 나에게 효과가 없었는지는 나에게 의문입니다.!

ReactiveClientRegistrationRepository 함께 됩니다.Reactive stack (netty)는다가 아닌Servlet stack (tomcat)

의 신이 .pom.xml포하다를 spring-boot-starter-web이 신이사는봄이해하용당을 하는 것을 이해합니다.Servlet stack로드될 것입니다.ClientRegistrationRepositoryReactiveClientRegistrationRepository

의 콩을 것.WebClient사용할 수 있는 두 가지 솔루션:

솔루션 1:

제다한을 합니다.spring-boot-starter-webpom.xml그래서 봄은 당신이 있는 것을 이해합니다.Reactive stack

@Bean
WebClient webClient(
    ReactiveClientRegistrationRepository clientRegistrationRepository,
    ReactiveOAuth2AuthorizedClientService authorizedClientService
) {
    var oauth = new ServerOAuth2AuthorizedClientExchangeFilterFunction(
            new AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager(
                clientRegistrationRepository, authorizedClientService
            )
        );

    oauth.setDefaultClientRegistrationId("AuthProvider");
    return WebClient.builder()
        .filter(oauth)
        .build();
}

솔루션 2:

지킨다spring-boot-starter-webpom.xml

@Bean // with spring-boot-starter-web
WebClient webClient(
    ClientRegistrationRepository clientRegistrationRepository,
    OAuth2AuthorizedClientService authorizedClientService
) {
    var oauth = new ServletOAuth2AuthorizedClientExchangeFilterFunction(
        new AuthorizedClientServiceOAuth2AuthorizedClientManager(
            clientRegistrationRepository, authorizedClientService
        )
    );
    oauth.setDefaultClientRegistrationId("AuthProvider");
    return WebClient.builder()
      .apply(oauth.oauth2Configuration())
      .build();
}

경우에는 제경에는을 합니다.WebClient춘투로.(WebApplicationType.NONE)그래서 서블릿 컨텍스트를 찾을 수 없어, 그래서 나는 그것을 구성해야 했습니다.ClientRegistrationRepository,OAuth2AuthorizedClientService,OAuth2AuthorizedClientManager혼자서


@Configuration
public class WebClientConfiguration {

    @Bean
    public ClientRegistrationRepository clientRegistrationsRepository(
            @Value("${keycloak.registration-id}") String registrationId,
            @Value("${keycloak.token-uri}") String tokenUri,
            @Value("${keycloak.client-id}") String clientId,
            @Value("${keycloak.client-secret}") String clientSecret) {
        ClientRegistration registration = ClientRegistration
                .withRegistrationId(registrationId)
                .tokenUri(tokenUri)
                .clientId(clientId)
                .clientSecret(clientSecret)
                .authorizationGrantType(CLIENT_CREDENTIALS)
                .build();
        return new InMemoryClientRegistrationRepository(registration);
    }

    @Bean
    public OAuth2AuthorizedClientService oAuth2AuthorizedClientService(ClientRegistrationRepository clientRegistrationsRepository) {
        return new InMemoryOAuth2AuthorizedClientService(clientRegistrationsRepository);
    }

    @Bean
    public OAuth2AuthorizedClientManager authorizedClientManager(
            ClientRegistrationRepository clientRegistrationRepository,
            OAuth2AuthorizedClientService authorizedClientService) {

        OAuth2AuthorizedClientProvider authorizedClientProvider =
                OAuth2AuthorizedClientProviderBuilder.builder()
                        .clientCredentials()
                        .build();

        AuthorizedClientServiceOAuth2AuthorizedClientManager authorizedClientManager =
                new AuthorizedClientServiceOAuth2AuthorizedClientManager(
                        clientRegistrationRepository, authorizedClientService);
        authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);

        return authorizedClientManager;
    }

    @Bean
    public WebClient webClient(OAuth2AuthorizedClientManager authorizedClientManager,
                               @Value("${keycloak.registration-id}") String registrationId) {

        ServletOAuth2AuthorizedClientExchangeFilterFunction auth2Function =
                new ServletOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager);
        auth2Function.setDefaultClientRegistrationId(registrationId);
        return WebClient.builder()
                .apply(auth2Function.oauth2Configuration())
                .build();

    }
}
keycloak:
  registration-id: my-registration
  client-id: my-parameters
  client-secret: g92olxcwBIWYNuSDaEyZrBsYHQPCv04R
  token-uri: http://localhost:8090/auth/realms/my-realm/protocol/openid-connect/token

다음과 같은 종속 요소를 추가했습니다.

    implementation "org.springframework.boot:spring-boot-starter-web"
    implementation "org.springframework.boot:spring-boot-starter-webflux"
    implementation "org.springframework.boot:spring-boot-starter-security"
    implementation "org.springframework.boot:spring-boot-starter-oauth2-resource-server"
    implementation "org.springframework.boot:spring-boot-starter-oauth2-client"

그것은 의존성 갈등 문제입니다.웹 종속성 제거 시도

언급URL : https://stackoverflow.com/questions/62446695/consider-defining-a-bean-of-type-org-springframework-security-oauth2-client-reg

반응형