如何覆盖 Spring Cloud OAuth2 客户端自动配置?

Posted

技术标签:

【中文标题】如何覆盖 Spring Cloud OAuth2 客户端自动配置?【英文标题】:How to overwrite Spring Cloud OAuth2 client autoconfiguration? 【发布时间】:2015-06-24 03:43:50 【问题描述】:

我们想要设置一个提供 REST API 的微服务,以便将其配置为 OAuth2 资源服务器。此服务还应充当具有客户端凭据授权的 OAuth2 客户端。这是配置:

spring.oauth2.client.id=clientCredentialsResource
spring.oauth2.client.accessTokenUri=http://localhost:9003/oauth/token
spring.oauth2.client.userAuthorizationUri=http://localhost:9003/oauth/authorize
spring.oauth2.client.grantType=client_credentials
spring.oauth2.client.clientId=<service-id>
spring.oauth2.client.clientSecret=<service-pw>

资源服务器部分工作正常。对于客户端部分,我们想使用 Feign、Ribbon 和 Eureka:

@FeignClient("user")
public interface UserClient

  @RequestMapping( method = RequestMethod.GET, value = "/user/uid")
  Map<String, String> getUser(@PathVariable("uid") String uid);

基于问题https://github.com/spring-cloud/spring-cloud-security/issues/56 中的要点,我创建了一个假装请求拦截器,它从假装请求标头中的自动连接的 OAuth2RestOperations 模板设置访问令牌

@Autowired
private OAuth2RestOperations restTemplate; 

template.header(headerName, String.format("%s %s", tokenTypeName, restTemplate.getAccessToken().toString()));

但这给了我调用用户服务的错误:

error="access_denied", error_description="Unable to obtain a new access token for resource 'clientCredentialsResource'. The provider manager is not configured to support it.

正如我所见,OAuth2ClientAutoConfiguration 始终为 Web 应用程序创建 AuthorizationCodeResourceDetails 实例,而不是仅用于非 Web 应用程序的必需 ClientCredentialsResourceDetails 实例。最后,无访问令牌提供者负责资源详细信息,并且调用失败

AccessTokenProviderChain.obtainNewAccessTokenInternal(AccessTokenProviderChain.java:146) 

我试图覆盖自动配置但失败了。有人可以给我一个提示吗?

【问题讨论】:

【参考方案1】:

要关闭此自动配置,您可以设置spring.oauth2.client.clientId=(空),(根据源代码),否则您必须在@EnableAutoConfiguration 中“排除”它。如果您这样做,您只需设置自己的OAuth2RestTemplate 并从您自己的配置中填写“真实”客户端 ID,例如

@Configuration
@EnableOAuth2Client
public class MyConfiguration 

  @Value("myClientId")
  String myClientId;

  @Bean
  @ConfigurationProperties("spring.oauth2.client")
  @Primary
  public ClientCredentialsResourceDetails oauth2RemoteResource() 
    ClientCredentialsResourceDetails details = new ClientCredentialsResourceDetails();
    details.setClientId(myClientId);
    return details;
  

  @Bean
  public OAuth2ClientContext oauth2ClientContext() 
    return new DefaultOAuth2ClientContext(new DefaultAccessTokenRequest());
  

  @Bean
  @Primary
  public OAuth2RestTemplate oauth2RestTemplate(
      OAuth2ClientContext oauth2ClientContext,
      OAuth2ProtectedResourceDetails details) 
    OAuth2RestTemplate template = new OAuth2RestTemplate(details,
      oauth2ClientContext);
    return template;
  


【讨论】:

感谢您的快速回答!这是我尝试过的。排除自动配置不起作用,因为自动连接依赖项失败。我现在尝试将 clientId 设置为空,但由于某种原因,我无法自动连接 OAuth2RestOperations restTemplate,而不是我想从中获取访问令牌。有什么想法吗? 我猜你也需要创建一个该类型的@Bean。我会更新答案中的代码。 @DaveSyer,设置 spring.oauth2.client.clientId='' (或看似等效,不设置)具有禁用 OAuth2SsoConfiguration 的额外副作用,事实证明我仍然需要。因为我需要自定义 OAuth2RestTemplate bean,所以我已经按照您在此处的建议替换了 OAuth2ClientAutoConfiguration,但是替换两者似乎只是为了自定义 OAuth2RestTemplate bean;你有其他建议吗? 是的,有一个*Customizer 回调(自此线程开始后添加)。如果您希望 SSO 具有自定义的休息模板,那就是这样做的方法。 @DaveSyer 你能扩展对 *Customizer 回调的引用吗?您能否提供一个示例或文档链接?我似乎找不到任何提及“Customizer 回调”或任何“*Customizer”类...

以上是关于如何覆盖 Spring Cloud OAuth2 客户端自动配置?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 spring oauth2 OAuth2AccessToken 请求上设置代理或如何覆盖 OAuth2AccessTokenSupport restTemplate 变量?

Spring Cloud Oauth2 初探

如何在spring + java中添加(覆盖)oAuth2访问令牌的到期时间

Spring Cloud Gateway 基于 OAuth2.0 的身份认证

Spring Cloud OAuth2 搭建授权服务

保障微服务 Spring Cloud 安全 Oauth2