关于Java:如何使用Spring Security 5在Spring Boot应用程序(而非Web应用程序)中获取oauth2访问令牌

How to get oauth2 access token in a spring boot application (not a web application) using spring security 5

我需要在我的Spring Boot应用程序的服务层中获取访问令牌(grant_type = client_credentials),以便与其他微服务(服务到服务的交互)进行对话。在这一层上没有spring http会话或auth,我只有client_id,client_secret和令牌url。这些属性在application.properties中设置为:

1
2
3
4
spring.security.oauth2.client.registration.auth1.client-id=***
spring.security.oauth2.client.registration.auth1.client-secret=***
spring.security.oauth2.client.registration.auth1.authorization-grant-type=client_credentials
spring.security.oauth2.client.provider.auth1.tokenUri=***

对于Spring Security OAuth来说,这似乎很简单,但是对于Spring Security却无法弄清。请参阅有关Spring Security 5的文档,但所有内容似乎都在Web界面的上下文中。我了解我可以通过http调用来获取具有我所拥有信息的令牌,但是我想利用该框架...

场景:
让我们将此称为Spring启动应用服务A。还有其他服务可能会调用A来处理http上的更新或发送有关A侦听的主题的kafka消息。当A处理更新/消息时,它需要向服务B发送一些数据,该服务需要authz的访问令牌。这是我需要访问令牌的地方。因此,交互本质上是服务-服务,并不特定于用户。


如果不在Web界面的上下文中,则需要查看服务层。

来自Spring Security的Javadocs中的AuthorizedClientServiceOAuth2AuthorizedClientManager

An implementation of an {@link OAuth2AuthorizedClientManager} that is capable of operating outside of a {@code HttpServletRequest} context, e.g. in a scheduled/background thread and/or in the service-tier.

这是一个可能有用的@Bean定义,我将在下面进行解释:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
    @Bean
    OAuth2AuthorizedClientManager authorizedClientManager
            (ClientRegistrationRepository clients) {
        OAuth2AuthorizedClientService service =
                new InMemoryOAuth2AuthorizedClientService(clients);
        AuthorizedClientServiceOAuth2AuthorizedClientManager manager =
                new AuthorizedClientServiceOAuth2AuthorizedClientManager(clients, service);
        OAuth2AuthorizedClientProvider authorizedClientProvider =
                OAuth2AuthorizedClientProviderBuilder.builder()
                        .clientCredentials()
                        .build();
        manager.setAuthorizedClientProvider(authorizedClientProvider);
        return manager;
    }

OAuth2AuthorizedClientManager管理授权的OAuth 2.0客户端定义。这些定义存储在ClientRegistrationRepository中,并且ClientRegistrationRepository的默认实例由Spring Boot通过已经定义的属性创建。

经理通常需要执行以下两项操作:

  • 第一个是OAuth2AuthorizedClientService,如果您想将令牌存储在数据库中,则非常方便-在Spring Security 5.2中,唯一的实现是内存中的实现。但是,似乎5.3将附带JDBC实现。

  • 第二个是OAuth2AuthorizedClientProvider,它实际上是执行令牌请求的对象,就像您要创建的客户端凭据一样。

创建此管理器后,您可以将其连接到Web客户端:

1
2
3
4
5
6
7
8
9
10
    @Bean
    WebClient webClient(OAuth2AuthorizedClientManager authorizedClientManager) {
        ServletOAuth2AuthorizedClientExchangeFilterFunction oauth2 =
                new ServletOAuth2AuthorizedClientExchangeFilterFunction
                        (authorizedClientManager);
        oauth2.setDefaultClientRegistrationId("auth1");
        return WebClient.builder()
                .apply(oauth2.oauth2Configuration())
                .build();
    }

上面使用的交换过滤器功能是将承载令牌添加到Authorization标头中的东西。它调用管理器要求它提供令牌,管理器将其从服务中拉出。如果已过期,则管理器要求提供者刷新它。现在,使用新令牌,管理器将其交给过滤器,以将其添加到请求中。