Spring 如何将RestTemplate与基本身份验证一起使用

Spring 如何将RestTemplate与基本身份验证一起使用,spring,spring-mvc,apache-httpclient-4.x,Spring,Spring Mvc,Apache Httpclient 4.x,如何使用ApacheHttpClient 4.3.2从Spring4.0.3.RELEASE配置RestTemplate?我遵循了SO、and甚至Apache的代码,它看起来非常简单,但对我来说从来都不起作用。当我使用curl和postman时,我可以验证是否正确发送了授权标头,但从未使用以下代码发送授权标头: public RestTemplate createBasicAuthTemplate(String username, String password) { BasicCred

如何使用ApacheHttpClient 4.3.2从Spring4.0.3.RELEASE配置RestTemplate?我遵循了SO、and甚至Apache的代码,它看起来非常简单,但对我来说从来都不起作用。当我使用curl和postman时,我可以验证是否正确发送了授权标头,但从未使用以下代码发送授权标头:

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");
ResponseEntity<String> response = basicAuth.getForEntity(url, String.class);
restemplate basicAuth=createbasicauthmplate(“user@app.com“,”密码“);
ResponseEntity response=basicAuth.getForEntity(url,String.class);

所以问题是:如何使用ApacheHttpClient 4.3.2从Spring4.0.3.RELEASE配置RestTemplate?上面的代码还有其他缺失的部分吗?在上面的代码中,RestTemplate是否使用了正确的方法?

精明的读者可能已经注意到授权标头从未发送,并意识到了这个问题。您只需要知道,发送未经授权的请求、接收带有WWW Authenticate头的401并使用Authorization头再次发出请求是一种标准协议(我不知道这一点,所以这是一个很好的解决方案)

rest模板不会在初始请求时发送身份验证标头(默认情况下,它是被动的,而不是主动的),因此,如果服务没有使用WWW身份验证标头进行响应(根据HTTP规范,它应该这样做),并且rest模板不会在初始响应后尝试发送凭据,然后调用将在初始401响应时失败

幸运的是,我们可以告诉rest模板在初始请求时发送凭据,而不是等待带有WWW认证头的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 {
    }
}

}