【问题标题】:Does spring security provide out of the box feature to retrieve and use OAuth2 token from a resource serverSpring Security 是否提供开箱即用的功能来从资源服务器检索和使用 OAuth2 令牌
【发布时间】:2022-02-17 16:35:03
【问题描述】:

我们有一个 Springboot 应用程序(比如说 microservice-A),并且要求我们应该添加一个带有 OAuth2 令牌的 HTTP 授权标头来访问我们的其他微服务之一(比如说 microservice-B)。此外,据说我们可以通过向同一个微服务-B 发送带有 Grant_type、Scope 和基本身份验证用户名和密码的 HTTP POST 请求来检索此 OAuth2 令牌。

现在我的疑问是,我们是否有任何来自 Spring 安全的开箱即用支持,以便在微服务 B 过期时自动从微服务 B 检索此 OAuth2 令牌并发送后续 HTTP 请求。或者这根本不需要,我应该首先通过从微服务-A 发送一个正常的 HTTP POST 请求来检索 OAuth2 令牌,然后发送后续请求。 (这样,每次我想发送请求或保存令牌并在过期时检索它时,我可能都必须检索 OAuth2 令牌)

微服务-A 是“客户端” Microservice-B 是“资源服务器”

【问题讨论】:

  • 你看过OAuth 2.0 Client的参考文档吗?
  • 感谢它的帮助 @SteveRiesenberg 使用了 client_credentials 授权类型流程

标签: spring-boot spring-security oauth-2.0 microservices


【解决方案1】:

使用org.springframework.boot:spring-boot-starter-oauth2-client 找到了解决方案。以下是配置基于 OAUTH2 的 WebClient 所需的配置,该 WebClient 可以自动从 auth-server (Microservice-B) 获取 OAUTH2 令牌并访问 resource-server (Microservice-B)。

application.properties

oauth2.client.registration.pgw.scope=all
oauth2.client.registration.pgw.client-id=client
oauth2.client.registration.pgw.client-secret=secret
oauth2.client.provider.pgw.token-uri=http://localhost:8082/oauth/token

Oauth2ClientConfiguration.java

@Configuration
public class Oauth2ClientConfiguration {
        
    @Bean
    public ReactiveClientRegistrationRepository getRegistration(
            @Value("${oauth2.client.provider.pgw.token-uri}") String tokenUri,
            @Value("${oauth2.client.registration.pgw.client-id}") String clientId,
            @Value("${oauth2.client.registration.pgw.client-secret}") String clientSecret,
            @Value("${oauth2.client.registration.pgw.scope}") String scope) {
        
        ClientRegistration registration = ClientRegistration
                                                .withRegistrationId(OAUTH2_CLIENT_REGISTRATION_ID)
                                                .tokenUri(tokenUri)
                                                .clientId(clientId)
                                                .clientSecret(clientSecret)
                                                .authorizationGrantType(CLIENT_CREDENTIALS)
                                                .scope(scope)
                                                .build();
        
        return new InMemoryReactiveClientRegistrationRepository(registration);
    }
    
    @Bean
    public WebClient webClient(ReactiveClientRegistrationRepository clientRegistrations) {
        InMemoryReactiveOAuth2AuthorizedClientService clientService = 
                new InMemoryReactiveOAuth2AuthorizedClientService(clientRegistrations);
        
        AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager authorizedClientManager = 
                new AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager(clientRegistrations, clientService);
        
        ServerOAuth2AuthorizedClientExchangeFilterFunction oauth = 
                new ServerOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager);
        oauth.setDefaultClientRegistrationId(OAUTH2_CLIENT_REGISTRATION_ID);
        
        return WebClient.builder().filter(oauth).build();
    }

}

然后我们可以使用这个 WebClient bean 向资源服务器发送 HTTP 请求,资源服务器将负责获取和管理 OAUTH2 令牌

webClient.get().uri("http://localhost:8080/api/private").retrieve().bodyToMono(String.class).block();

【讨论】:

    猜你喜欢
    • 2017-12-15
    • 2015-06-18
    • 2021-01-07
    • 2013-12-21
    • 2020-12-29
    • 2019-11-27
    • 2022-08-21
    • 1970-01-01
    • 2018-07-08
    相关资源
    最近更新 更多