如何覆盖 Spring Cloud OAuth2 客户端自动配置?
How to overwrite Spring Cloud OAuth2 client autoconfiguration?
我们想要设置一个提供 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 模板的访问令牌 header
@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 的实例,而不是仅用于 non-web 应用程序的必需的 ClientCredentialsResourceDetails 实例。最后,无访问令牌提供者负责资源详细信息,并且调用在
中失败
AccessTokenProviderChain.obtainNewAccessTokenInternal(AccessTokenProviderChain.java:146)
我试图覆盖自动配置但失败了。有人可以告诉我怎么做吗?
要关闭这部分自动配置,您可以设置 spring.oauth2.client.clientId=
(空),(根据源代码),否则您必须在 @EnableAutoConfiguration
中 "exclude"。如果这样做,您可以设置自己的 OAuth2RestTemplate
并从您自己的配置中填写 "real" 客户端 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;
}
}
我们想要设置一个提供 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 模板的访问令牌 header
@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 的实例,而不是仅用于 non-web 应用程序的必需的 ClientCredentialsResourceDetails 实例。最后,无访问令牌提供者负责资源详细信息,并且调用在
中失败AccessTokenProviderChain.obtainNewAccessTokenInternal(AccessTokenProviderChain.java:146)
我试图覆盖自动配置但失败了。有人可以告诉我怎么做吗?
要关闭这部分自动配置,您可以设置 spring.oauth2.client.clientId=
(空),(根据源代码),否则您必须在 @EnableAutoConfiguration
中 "exclude"。如果这样做,您可以设置自己的 OAuth2RestTemplate
并从您自己的配置中填写 "real" 客户端 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;
}
}