如何使用Apache httpclient 4.3.2从Spring 4.0.3.RELEASE配置RestTemplate?我跟着代码SO 这里,并在这里,甚至可以从Apache的这里,似乎很简单,但它从来没有为我工作.我可以验证在使用curl和postman时是否正确发送了Authorization标头,但是从未使用以下代码发送Authorization标头:
public RestTemplate createBasicAuthTemplate(String username, String password) { BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider(); credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(username, password)); HttpClient httpClient = HttpClientBuilder.create() .setDefaultCredentialsProvider(credentialsProvider) .build(); ClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(httpClient); RestTemplate template = new RestTemplate(requestFactory); return template; }
并且代码被调用如下:
RestTemplate basicAuth = createBasicAuthTemplate("user@app.com", "password"); ResponseEntityresponse = basicAuth.getForEntity(url, String.class);
所以问题是:如何使用Apache httpclient 4.3.2从Spring 4.0.3.RELEASE配置RestTemplate?还有其他部分缺少上述代码吗?在上面的代码中是使用正确方法的RestTemplate吗?
精明的读者可能已经注意到永远不会发送Authorization标头,并意识到了问题.您只需要知道发送未经授权的请求是一个标准协议,接收带有WWW-Authenticate标头的401,并使用Authorization标头再次发出请求(我不知道,所以这是一个很好的学习经验).
其余模板不会在初始请求上发送Authentication头(默认情况下它是被动的而不是主动的),因此如果服务没有响应WWW-Authenticate头(因为它应该根据HTTP规范)和RestTemplate在初始响应之后不会尝试发送凭据,然后该呼叫将在初始401响应中失败.
幸运的是,我们可以告诉其余模板在初始请求上发送凭据,而不是等待带有WWW-Authenticate头的401.
这是执行此操作的代码.这里的技巧是覆盖请求工厂的createHttpContext()方法以控制HTTP上下文,并使用此工厂构建RestTemplate.此代码有效,并使用自签名证书.您当然可以根据自己的喜好对其进行重组......
public class BasicRequestFactory extends HttpComponentsClientHttpRequestFactory { public BasicRequestFactory(HttpClient httpClient) { super(httpClient); } @Override protected HttpContext createHttpContext(HttpMethod httpMethod, URI uri) { HttpHost targetHost = new HttpHost(uri.getHost(), uri.getPort(), uri.getScheme()); AuthCache authCache = new BasicAuthCache(); BasicScheme basicAuth = new BasicScheme(); authCache.put(targetHost, basicAuth); BasicHttpContext localContext = new BasicHttpContext(); localContext.setAttribute(ClientContext.AUTH_CACHE, authCache); return localContext; } private static HttpClient createSecureClient() throws NoSuchAlgorithmException, KeyStoreException, KeyManagementException { SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(null, new TrustSelfSignedStrategy()).useTLS().build(); SSLConnectionSocketFactory connectionFactory = new SSLConnectionSocketFactory(sslContext, new AllowAllHostnameVerifier()); return HttpClientBuilder.create().setSSLSocketFactory(connectionFactory).build(); } private static HttpClient createSecureClient(String username, String password) throws NoSuchAlgorithmException, KeyStoreException, KeyManagementException { BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider(); credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(username, password)); SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(null, new TrustSelfSignedStrategy()).useTLS().build(); SSLConnectionSocketFactory connectionFactory = new SSLConnectionSocketFactory(sslContext, new AllowAllHostnameVerifier()); return HttpClientBuilder.create().setSSLSocketFactory(connectionFactory).setDefaultCredentialsProvider(credentialsProvider).build(); } public static RestTemplate createTemplate(String username, String password) throws NoSuchAlgorithmException, KeyStoreException, KeyManagementException { RestTemplate template = new RestTemplate(new BasicRequestFactory(createSecureClient(username, password))); template.setErrorHandler(new NopResponseErrorHandler()); return template; } public static RestTemplate createTemplate() throws NoSuchAlgorithmException, KeyStoreException, KeyManagementException { RestTemplate template = new RestTemplate(new BasicRequestFactory(createSecureClient())); template.setErrorHandler(new NopResponseErrorHandler()); return template; } private static class NopResponseErrorHandler implements ResponseErrorHandler { @Override public boolean hasError(ClientHttpResponse chr) throws IOException { return false; } @Override public void handleError(ClientHttpResponse chr) throws IOException { } } }