基于运行时的凭据创建不同的 Oauth2RestTemplates

Posted

技术标签:

【中文标题】基于运行时的凭据创建不同的 Oauth2RestTemplates【英文标题】:Creating different Oauth2RestTemplates based on credentials on Runtime 【发布时间】:2020-11-18 09:08:20 【问题描述】:

我有一个 OAuth2RestTemplate 定义如下

@Configuration
@EnableOAuth2Client
public class TestOauth
        
@Bean
public OAuth2RestTemplate restTemplate()
OAuth2RestTemplate restTemplate= new OAuth2RestTemplate(buildResourceDetails());
restTemplate.setRequestFactory(new BufferingClientHttpRequestFactory(new 
HttpComponentsClientHttpRequestFactory()));
return restTemplate;

    
@Bean
public ClientCredentialsResourceDetails buildResourceDetails()
ClientCredentialsResourceDetails resourceDetails = new ClientCredentialsResourceDetails();
resourceDetails.setClientId("TestId");
resourceDetails.setClientSecret("TestSecret");
resourceDetails.setAccessTokenUri("TestURI");
return resourceDetails;

现在,在调用类中,我将其注释如下,它工作正常。

@Autowired
private OAuth2RestTemplate restTemplate;

我想使这个功能通用,并基于非 clientId、secret 和 URI 创建模板。我怎样才能做到这一点?是否创建多个 @bean 方法(每个凭据的单独方法)并基于调用者凭据,从映射中选择相应的 bean 可能是实现此目的的唯一方法?

我尝试只保留一个 @bean 方法并将参数传递给 restTemplate 方法,但我一直遇到 没有找到 [java.lang.String] 类型的合格 bean 错误

请指教

【问题讨论】:

你有多少个clientId? 现在大约 3 个,但我们正在考虑在不久的将来增加到 20 个。 【参考方案1】:

如果您有几个clientId,例如3 或4,则可以拥有多个OAuth2RestTemplate 类型的bean 并使用不同的名称并使用它们。如果您想采用这种方法,请阅读以下链接以在地图中自动装配多个 bean:

Spring Autowire Bean with multiple Interface Implementations, define Implementation in method

但如果您知道ClientId 的数量会根据某些参数动态变化,您可以使用OAuth2RestTemplate 类型的一个bean,并在运行时使用RestTemplate Interceptor 更改clientId 标头的值。

阅读以下链接了解如何使用Interceptor

https://howtodoinjava.com/spring-boot2/resttemplate/clienthttprequestinterceptor/

如果您确定在运行时根据请求中的参数传递客户端 ID,您可以这样做:

private HttpHeaders createHttpHeaders(String clientId, String secret)

    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_JSON);
    headers.add("client_id", clientId);
    headers.add("client_secret", secret);
    return headers;


private void yourserviceMethod() 

    String theUrl = "http://blah.blah.com:8080/rest/api/blah";
    try 
        HttpHeaders headers = createHttpHeaders("clintId", "secret", "accessToken");
        HttpEntity<String> entity = new HttpEntity<String>("parameters", headers);
        ResponseEntity<String> response = restTemplate.exchange(theUrl, HttpMethod.GET, entity, String.class);
        System.out.println("Result - status ("+ response.getStatusCode() + ") has body: " + response.hasBody());
    
    catch (Exception eek) 
        System.out.println("** Exception: "+ eek.getMessage());
    

【讨论】:

Super.. 类似于肥皂处理程序对吧?让我看看谢谢。 实际上拦截器不起作用,因为凭据是根据某些条件选择的,而不是存储在属性文件中。 您的意思是您想决定将哪个clientId 设置为您的服务中的标头?如果这是您的要求,您可以在服务中调用 Restemplate 方法时将 clientId 设置为标头 如何在运行时将 clientid 传递给拦截器? 我无法根据拦截器中请求的详细信息来区分选择哪个clientid。

以上是关于基于运行时的凭据创建不同的 Oauth2RestTemplates的主要内容,如果未能解决你的问题,请参考以下文章

在 C# 中使用不同的凭据调用远程 powershell 脚本

将凭据添加到与本地系统帐户不同的帐户

JVM 运行时的内存分配

JVM 运行时的内存分配

通过 Tweepy 在 Twitter 上更新状态时的回溯

Python Virtualenv 介绍