RestTemplate使用当前httpclient(4.x)进行基本或摘要式身份验证

时间:2012-02-21 11:13:14

标签: spring restful-authentication http-authentication http-basic-authentication resttemplate

我正在尝试使用 RestTemplate httpclient(4.x)进行Digest主要(或基本)身份验证。

由于我找不到任何关于如何实际执行此操作的相关示例,我尝试了各种方法来挂钩各种httpclient工件,没有运气 - 实质上,没有发送身份验证标头所有

我目前的实施是:

DefaultHttpClient newHttpClient = new DefaultHttpClient();
Credentials credentials = new UsernamePasswordCredentials( username, password );
AuthScope authScope = new AuthScope( host, port, AuthScope.ANY_REALM );
BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials( authScope, credentials );
newHttpClient.setCredentialsProvider( credentialsProvider );

HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory( newHttpClient );
restTemplate.setRequestFactory( requestFactory );

我有什么问题吗?这个地方还有一个可行的例子吗? 任何帮助表示赞赏。 谢谢。

3 个答案:

答案 0 :(得分:9)

尝试实现自己的RequestFactory以实现抢占式身份验证。

public class PreEmptiveAuthHttpRequestFactory extends HttpComponentsClientHttpRequestFactory {

public PreEmptiveAuthHttpRequestFactory(DefaultHttpClient client) {
    super(client);
}

@Override
protected HttpContext createHttpContext(HttpMethod httpMethod, URI uri) {
    AuthCache authCache = new BasicAuthCache();
    BasicScheme basicAuth = new BasicScheme();
    HttpHost targetHost = new HttpHost(uri.getHost(), uri.getPort());
    authCache.put(targetHost, basicAuth);
    BasicHttpContext localcontext = new BasicHttpContext();
    localcontext.setAttribute(ClientContext.AUTH_CACHE, authCache);

    return localcontext;
}
}

然后只需使用它:

HttpComponentsClientHttpRequestFactory requestFactory = new PreEmptiveAuthHttpRequestFactory( newHttpClient );

希望有所帮助


如何设置用户名和密码(复制自@ bifur的评论)

您可以使用UserNamePasswordCredentials

UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(getUsername(),getPassword()); 
client.getCredentialsProvider().setCredentials(new AuthScope(getHost(), getPort(), AuthScope.ANY_REALM), credentials); 

只需在上一个工厂中使用客户端

HttpComponentsClientHttpRequestFactory requestFactory = new PreEmptiveAuthHttpRequestFactory(client);

答案 1 :(得分:1)

使用最新版本的Spring和HttpClient,它们使基本身份验证和摘要身份验证变得非常容易。

注意:我正在使用 Spring Boot 2.x.x (Spring Framework 5.x.x)和 HttpClient 4.5.x


配置RestTemplate

我们可以将RestTemplate配置为进行抢占非抢占(默认)基本身份验证或摘要身份验证。

非抢先基本或摘要身份验证设置

RestTemplate使用非抢占式(即最初执行质询请求)基本身份验证或摘要身份验证的设置是相同的。只需通过HttpClient库的CredentialsProvider类提供用户名和密码。

HttpClient将基于初始请求(挑战请求)的401响应标头自动检测服务器正在使用哪种身份验证类型,因此无需进行任何特定于身份验证类型的配置。

@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
    Credentials credentials = new UsernamePasswordCredentials(username, password);
    CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
    credentialsProvider.setCredentials(AuthScope.ANY, credentials);

    HttpClient httpClient = HttpClients
            .custom()
            .setDefaultCredentialsProvider(credentialsProvider)
            .build();

    return builder
            .requestFactory(() -> new HttpComponentsClientHttpRequestFactory(httpClient))
            .build();
}

抢先式基本身份验证设置

借助抢先式基本身份验证,Spring更加轻松地支持它。由于只需要用户名和密码,建议使用抢占式基本身份验证来消除执行质询请求的额外费用。

@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
    return builder
            .basicAuthorization(username, password)
            .build();
}

抢先式摘要身份验证设置

Spring不支持开箱即用的RestTemplate抢占式摘要身份验证。由于摘要身份验证需要用户名和密码之外的随机数和其他可能由服务器生成的数据(例如,不透明的)来进行身份验证,因此必须至少提出一个质询请求。

鉴于此,尽管直接使用HttpClient的库,仍然可以使用抢占式摘要身份验证。如果您仍然想对RestTemplate使用摘要抢占式身份验证,请注意在连接到不受Spring摘要保护的应用程序时可能会遇到一些问题。

请参考先前的答案以使用抢占式摘要身份验证。考虑到复杂性和可能遇到的问题,我个人不建议对RestTemplate使用抢占式摘要身份验证。使用抢占式摘要身份验证的主要动机是为了提高性能,因此除非您对每个请求进行多次调用,否则非抢先式摘要身份验证可能是一个更好的选择。


使用RestTemplate发送请求

使用RestTemplate发送请求时,不需要任何特定于身份验证类型的处理。无论您使用抢占式身份验证还是非抢占式身份验证,发送请求的代码都相同。

示例GET请求

String response = restTemplate.getForObject(url, String.class);
JSONObject result = new JSONObject(response);

示例POST请求

JSONObject body = new JSONObject();
// populate body

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);

HttpEntity<String> request = new HttpEntity<>(body, headers);
String response = restTemplate.postForObject(url, request, String.class);
JSONObject result = new JSONObject(response);

答案 2 :(得分:0)

我修改了原始答案:

  • 添加了https支持
  • 更新了被删除的内容

    public class PreEmptiveAuthHttpRequestFactory extends HttpComponentsClientHttpRequestFactory {
    
        public PreEmptiveAuthHttpRequestFactory(HttpClient client) {
            super(client);
        }
    
        @Override
        protected HttpContext createHttpContext(HttpMethod httpMethod, URI uri) {
            AuthCache authCache = new BasicAuthCache();
            BasicScheme basicAuth = new BasicScheme();
            HttpHost targetHost = new HttpHost(uri.getHost(), uri.getPort(), uri.getScheme());
            authCache.put(targetHost, basicAuth);
            HttpClientContext localContext = HttpClientContext.create();
            localContext.setAuthCache(authCache);
            return localContext;
        }
    }