我使用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);
感谢。
答案 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);