OAuth2RestTemplate TCP连接

时间:2018-03-21 19:33:54

标签: spring spring-boot spring-rest

我使用Spring OAuth2RestTemplate和ClientCredentialsResourceDetails获取API授权令牌。授权服务器和API端点隐藏在相同的负载平衡器(LB)之后。我们遇到的问题是,在获取令牌后,与API端点的第一次连接失败并显示404错误消息,但后续使用相同令牌的同一API端点的调用成功。我相信LB在某种程度上是错误配置的,但是我们已经被问到是否可以尝试使用单独的TCP会话来获取令牌然后是REST调用。有没有办法让Spring RestTemplate这样做?

更新

以下是我创建和配置模板的方法:

@Bean
public OAuth2RestTemplate oauth2RestTemplate(
    @Value("${token.uri}") final String tokenUri, 
    @Value("${token.clientId:client}") final String clientId, 
    @Value("${token.secret:secret}") final String clientSecret, 
    @Value("${token.scope:platform}") final String scope, 
    final MappingJackson2HttpMessageConverter customJackson2HttpMessageConverter)
{
   ClientCredentialsResourceDetails rd = new 
   ClientCredentialsResourceDetails();
   rd.setAuthenticationScheme(AuthenticationScheme.header);
   rd.setAccessTokenUri(tokenUri);
   rd.setClientId(clientId);
   rd.setClientSecret(clientSecret);
   rd.setScope(Arrays.asList(scope));

   OAuth2RestTemplate rt = new OAuth2RestTemplate(rd);

   List<HttpMessageConverter<?>> converters = rt.getMessageConverters();
   converters.add(customJackson2HttpMessageConverter);
   rt.setMessageConverters(converters);

   return rt;
}

这里是对api的调用:

HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
headers.set("Connection", "close"); // hmm, gets replace by keep-alive on the token api request!        
HttpEntity<String> entity = new HttpEntity<String>(headers);

ResponseEntity<MyObject[]> response = restTemplate.exchange(
   "http://example.com/api/v1/rest/method", 
   HttpMethod.GET, entity, MyObject[].class);

感谢。

1 个答案:

答案 0 :(得分:0)

在使用resttemplate发送请求时,尝试添加Connection请求标头,其值为close。这应该强制在每次请求后关闭TCP连接。虽然性能不是很好。

HttpHeaders headers = new HttpHeaders();
headers.set("Connection", "close");

这仅适用于“但是我们被问到是否可以尝试使用单独的TCP会话来获取令牌,然后再使用REST调用。”部分问题。它无助于解决你的404(这似乎是一个LB问题)。

更新:由于您使用的是OAuth2RestTemplate,请创建一个注入标题的ClientHttpRequestInterceptor

public class ConnectionCloseInterceptor implements ClientHttpRequestInterceptor {
    public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
        HttpHeaders headers = request.getHeaders();
        headers.add("Connection", "close");
        return execution.execute(request, body);
    }
}

在你的rest模板中使用它(OAuth2RestTemplate扩展RestTemplate以便下面适用于这两者),就像这样(当你创建其余的模板bean时):

List<ClientHttpRequestInterceptor> currentInterceptors = new ArrayList<>(restTemplate.getInterceptors()); //Don't want to lose the other interceptors!
currentInterceptors.add(new ConnectionCloseInterceptor()); //Add ours
restTemplate.setInterceptors(currentInterceptors);