将 OAuth2RestTemplate 公开为 AsyncRestTemplate

Posted

技术标签:

【中文标题】将 OAuth2RestTemplate 公开为 AsyncRestTemplate【英文标题】:Exposing OAuth2RestTemplate as AsyncRestTemplate 【发布时间】:2015-12-28 20:34:19 【问题描述】:

我有一个有效的 OAuth2RestTemplate 客户端(我使用的是 spring-security-oauth2 2.0.7.RELEASE)。现在我想将它公开/包装为 AsyncRestTemplate 以利用 ListenableFuture 的异步语义。不幸的是,以下简单的方法不起作用:

// instantiate and configure OAuth2RestTemplate - works
OAuth2RestTemplate oAuth2RestTemplate = new OAuth2RestTemplate(...);

// wrap sync restTemplate with AsyncRestTemplate - doesn't work 
AsyncRestTemplate asyncRestTemplate = new AsyncRestTemplate(
    new HttpComponentsAsyncClientHttpRequestFactory(), oAuth2RestTemplate);

如何为我的 HTTP 服务获取 OAuth2 Rest 客户端作为 AsyncRestTemplate?

【问题讨论】:

【参考方案1】:

好的,我可以通过使用 OAuth2RestTemplate 中的 accessToken 手动设置“授权”标头来使 AsyncRestTemplate 工作;这是 Spring Java 配置:

@Bean
public OAuth2RestTemplate restTemplate() 
    ClientCredentialsResourceDetails details = new ClientCredentialsResourceDetails();
    // configure oauth details

    OAuth2RestTemplate restTemplate = new OAuth2RestTemplate(details);
    restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory());

    return restTemplate;


@Bean
public AsyncRestTemplate asyncRestTemplate(final OAuth2RestTemplate oAuth2RestTemplate) 
    HttpComponentsAsyncClientHttpRequestFactory asyncRequestFactory = new HttpComponentsAsyncClientHttpRequestFactory() 
        @Override
        public AsyncClientHttpRequest createAsyncRequest(URI uri, HttpMethod httpMethod) throws IOException 
            AsyncClientHttpRequest asyncRequest = super.createAsyncRequest(uri, httpMethod);

            OAuth2AccessToken accessToken = oAuth2RestTemplate.getAccessToken();
            asyncRequest.getHeaders().set("Authorization", String.format("%s %s", accessToken.getTokenType(), accessToken.getValue()));

            return asyncRequest;
        
    ;
    return new AsyncRestTemplate(asyncRequestFactory, oAuth2RestTemplate);

我希望有更简单的方法在 Spring 中将配置的 OAuth2RestTemplate 公开为 AsyncRestTemplate。

【讨论】:

【参考方案2】:

上述方法可行,但我找到了一种更简洁的方法。 注册一个实现AsyncClientHttpRequestInterceptor

示例代码:

private class Oauth2RequestInterceptor implements AsyncClientHttpRequestInterceptor

    private final OAuth2RestTemplate oAuth2RestTemplate;

    public Oauth2RequestInterceptor( OAuth2RestTemplate oAuth2RestTemplate )
    
        this.oAuth2RestTemplate = oAuth2RestTemplate;
    

    public ListenableFuture<ClientHttpResponse> intercept( HttpRequest request, byte[] body,
        AsyncClientHttpRequestExecution execution ) throws IOException
    
        OAuth2AccessToken accessToken = oAuth2RestTemplate.getAccessToken();
        request.getHeaders()
            .set( "Authorization", String.format( "%s %s", accessToken.getTokenType(), accessToken.getValue() ) );
        return execution.executeAsync( request, body );
    

然后用你的AsyncRestTemplate注册:

@Bean
public AsyncRestTemplate asyncRestTemplate( AsyncClientHttpRequestFactory factory, OAuth2RestTemplate restTemplate )

    AsyncRestTemplate asyncRestTemplate = new AsyncRestTemplate( factory, restTemplate );
    asyncRestTemplate.setInterceptors( Collections.singletonList( new Oauth2RequestInterceptor( restTemplate ) ) );
    return asyncRestTemplate;

【讨论】:

以上是关于将 OAuth2RestTemplate 公开为 AsyncRestTemplate的主要内容,如果未能解决你的问题,请参考以下文章

无法将 @LoadBalanced 与在 ClientCredentials 上配置的 OAuth2RestTemplate 一起使用

Spring OAuth2RestTemplate 在配置为使用 JWT 时丢失令牌

带有预取 JWT 令牌的 OAuth2RestTemplate

如何设置 OAuth2RestTemplate(更新后)

如何使用 OAuth2RestTemplate + Spring 4?

在安全上下文中保存 Oauth2RestTemplate/Client 存储