我尝试使用springwebclient和springsecurityoauth2客户端在两个应用程序之间进行通信。我需要使用oauth2客户端凭据授予类型,并对这些应用程序之间的所有请求使用相同的凭据和相同的令牌。在oauth2术语中,资源所有者是应用程序a本身,而资源服务器是应用程序b(它是key斗篷管理api)。我使用application.yaml和servlet环境中的spring引导自动配置。所以我就这样实现了:
WebClient buildWebClient(ClientRegistrationRepository clientRegistrationRepository,
OAuth2AuthorizedClientRepository authorizedClientRepository, String clientName) {
final ServletOAuth2AuthorizedClientExchangeFilterFunction oauth2Client = new ServletOAuth2AuthorizedClientExchangeFilterFunction(
clientRegistrationRepository, authorizedClientRepository);
oauth2Client.setDefaultClientRegistrationId(clientName);
return WebClient.builder()
.apply(oauth2Client.oauth2Configuration())
.build();
}
我发现我有一个问题,并且无效的令牌(我使用keydepot,如果我的keydepot重新启动,那么所有旧的令牌都是无效的)永远不会被删除(您可以在问题#9477中看到),所以我开始在中调试整个授权过程 ServletOAuth2AuthorizedClientExchangeFilterFunction
. 我发现令牌是按应用程序a的每个用户保存的。这意味着应用程序a的每个用户都有自己的令牌来授权应用程序b。但这不是我想要的行为,我只想在应用程序a中使用一个令牌来消耗来自应用程序b的资源。
我认为我找到了两个解决方案,但它们都不是最优的。
解决方案1:在之后添加另一个默认请求 ServletOAuth2AuthorizedClientExchangeFilterFunction
它取代了用户 Authentication
应用程序在属性中 Authentication
. 问题是它依赖于 ServletOAuth2AuthorizedClientExchangeFilterFunction
使用私有属性 AUTHENTICATION_ATTR_NAME = Authentication.class.getName();
.
return WebClient.builder()
.apply(oauth2Client.oauth2Configuration())
.defaultRequest(spec -> spec.attributes(attr ->
attr.put(AUTHENTICATION_ATTR_NAME, new CustomApplicaitonAuthentication())
)
.build();
解决方案2:使用 OAuth2AuthorizedClientRepository
而不是默认值 AuthenticatedPrincipalOAuth2AuthorizedClientRepository
(由于删除无效令牌的问题,我不得不这样做)我忽略了用户的 Authentication
我使用自定义应用程序 Authentication
.
@Override
public <T extends OAuth2AuthorizedClient> T loadAuthorizedClient(String clientRegistrationId, Authentication principal,
HttpServletRequest request) {
return this.authorizedClientService.loadAuthorizedClient(clientRegistrationId, new CustomApplicaitonAuthentication());
}
@Override
public void saveAuthorizedClient(OAuth2AuthorizedClient authorizedClient, Authentication principal,
HttpServletRequest request, HttpServletResponse response) {
this.authorizedClientService.saveAuthorizedClient(authorizedClient, new CustomApplicaitonAuthentication());
}
但我认为我的两个解决方案都不是最优的。有没有其他方法可以更直接地做到这一点?
1条答案
按热度按时间ccgok5k51#
我找到了解决方案,因为我需要在没有servlet请求(消息传递、调度程序等)的情况下运行它。因此我需要更新它并使用
AuthorizedClientServiceOAuth2AuthorizedClientManager
而不是默认值DefaultOAuth2AuthorizedClientManager
. 然后我意识到它做的和我需要的一样。我们必须增加一个自定义
OAuth2AuthorizationFailureHandler
因为如果你不使用这个构造函数ServletOAuth2AuthorizedClientExchangeFilterFunction(ClientRegistrationRepository clientRegistrationRepository, OAuth2AuthorizedClientRepository authorizedClientRepository)
你用一个自定义的OAuth2AuthorizedClientManager
然后它没有配置,您必须手动执行。