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

Dan*_*ass 9 spring spring-security spring-boot spring-security-oauth2 spring-cloud

我们想要设置一个提供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>
Run Code Online (Sandbox Code Playgroud)

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

@FeignClient("user")
public interface UserClient
{
  @RequestMapping( method = RequestMethod.GET, value = "/user/{uid}")
  Map<String, String> getUser(@PathVariable("uid") String uid);
}
Run Code Online (Sandbox Code Playgroud)

基于问题的主旨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()));
Run Code Online (Sandbox Code Playgroud)

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

error="access_denied", error_description="Unable to obtain a new access token for resource 'clientCredentialsResource'. The provider manager is not configured to support it.
Run Code Online (Sandbox Code Playgroud)

正如我所看到的,OAuth2ClientAutoConfiguration始终为Web应用程序创建AuthorizationCodeResourceDetails实例,但不创建仅用于非Web应用程序的必需ClientCredentialsResourceDetails.最后,no access token privider负责资源详细信息并且调用失败

AccessTokenProviderChain.obtainNewAccessTokenInternal(AccessTokenProviderChain.java:146) 
Run Code Online (Sandbox Code Playgroud)

我试图覆盖自动配置但失败了.有人可以给我一个提示怎么做?

Dav*_*yer 8

要关闭这个自动配置,你可以设置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;
  }

}
Run Code Online (Sandbox Code Playgroud)

  • @DaveSyer,设置 spring.oauth2.client.clientId='' (或看似等效地,不设置)具有禁用 OAuth2SsoConfiguration 的额外副作用,事实证明我仍然需要。因为我需要自定义 OAuth2RestTemplate bean,所以我已经按照您在这里的建议替换了 OAuth2ClientAutoConfiguration,但是为了自定义 OAuth2RestTemplate bean 而替换两者似乎很多;你有其他建议吗? (2认同)
  • 是的,有一个 `*Customizer` 回调(自该线程启动后添加)。如果您希望使用自定义的休息模板进行 SSO,那就是这样做的方法。 (2认同)