在已认证的用户会话中通过OpenFeign调用微服务

后端开发 2026-07-11

我有一个设置,用来使用Keycloak进行用户身份验证。我使用Spring Boot和 Spring Security。我的后端通过Keycloak使用 authorization_code 授权(grant)成功完成认证,并获取了ID Token、Access Token和 Refresh Token。接下来,我搭建一个OpenFeign客户端,从其他微服务获取额外数据,这样当用户向后端发出请求时,后端就可以返回所需的全部数据。

共有两层通信:

  • 用户到后端
  • 后端到微服务

默认情况下,后端到微服务的通信属于 client_credentials 授权(grant),我已成功设置。OpenFeign使用 AuthorizedClientServiceOAuth2AuthorizedClientManager,它专门针对 client_credentials 授权(grant)进行定制。它使用Keycloak获取访问令牌,当令牌过期时会再次获取。

我发现的问题是,我对Keycloak定义了两套客户端配置,产生两套令牌:

  • 用户到后端所需的ID Token、Access Token和 Refresh Token
  • 后端到微服务所需的单独的Access Token

是否有可能统一使用同一个Access Token?我可以只有一个配置(用户到后端),让OpenFeign使用其中的Access Token,并自动刷新它吗?我还没有找到一个优雅的实现方式。

解决方案

OpenFeign通过 org.springframework.cloud.openfeign.FeignAutoConfiguration 使用默认配置,在这里有这样一个Bean:

@Bean  
OAuth2AuthorizedClientManager feignOAuth2AuthorizedClientManager(  
    ClientRegistrationRepository clientRegistrationRepository,  
    OAuth2AuthorizedClientService oAuth2AuthorizedClientService  
) {  
    return new AuthorizedClientServiceOAuth2AuthorizedClientManager(clientRegistrationRepository, oAuth2AuthorizedClientService);  
}

AuthorizedClientServiceOAuth2AuthorizedClientManager 内部仅支持 "client_credentials" 授权(grant)。这很合理,因为OpenFeign主要设计用于机器对机器(M2M)的授权流程。

为了让OpenFeign使用通过 "authorization_code" 获取到的Access Token(就像人类用户认证的情况),需要用我们自己的实现来替换这个Bean。我们可以在Spring @Configuration 中定义如下:

@Bean  
OAuth2AuthorizedClientManager feignOAuth2AuthorizedClientManager(  
    ClientRegistrationRepository clientRegistrationRepository,  
    OAuth2AuthorizedClientRepository oAuth2AuthorizedClientRepository  
) {  
    return new DefaultOAuth2AuthorizedClientManager(clientRegistrationRepository, oAuth2AuthorizedClientRepository);  
}

DefaultOAuth2AuthorizedClientManager 支持 "authorization_code"、"refresh_token" 和 "client_credentials"。它将轮换它们,最终获得正确的Access Token,或在它过期时刷新它。

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章