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

Eug*_*gen 10 spring restful-authentication http-authentication basic-authentication resttemplate

我正在尝试使用RestTemplatehttpclient(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 );
Run Code Online (Sandbox Code Playgroud)

有什么我做错了吗?这个地方还有一个可行的例子吗?任何帮助表示赞赏.谢谢.

bif*_*fur 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;
}
}
Run Code Online (Sandbox Code Playgroud)

然后只需使用它:

HttpComponentsClientHttpRequestFactory requestFactory = new PreEmptiveAuthHttpRequestFactory( newHttpClient );
Run Code Online (Sandbox Code Playgroud)

希望能帮助到你


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

您可以使用 UserNamePasswordCredentials

UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(getUsername(),getPassword()); 
client.getCredentialsProvider().setCredentials(new AuthScope(getHost(), getPort(), AuthScope.ANY_REALM), credentials); 
Run Code Online (Sandbox Code Playgroud)

只需在以前的工厂中使用客户端即可

HttpComponentsClientHttpRequestFactory requestFactory = new PreEmptiveAuthHttpRequestFactory(client);
Run Code Online (Sandbox Code Playgroud)

  • 您可以使用UserNamePasswordCredentials`UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(getUsername(),getPassword()); client.getCredentialsProvider().setCredentials(new AuthScope(getHost(),getPort(),AuthScope.ANY_REALM),credentials);`并且只使用上一个工厂中的客户端`HttpComponentsClientHttpRequestFactory requestFactory = new PreEmptiveAuthHttpRequestFactory(client);` (3认同)

Max*_*mos 5

借助最新版本的 Spring 和 HttpClient,可以轻松执行基本身份验证和摘要身份验证。

注意:我使用的是Spring Boot 2.xx (Spring Framework 5.xx) 和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();
}
Run Code Online (Sandbox Code Playgroud)

抢占式基本身份验证设置

通过抢占式基本身份验证,它变得更加容易,Spring 开箱即用地支持它。由于只需要用户名和密码,因此建议使用抢占式基本身份验证来消除执行质询请求的额外成本。

@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
    return builder
            .basicAuthorization(username, password)
            .build();
}
Run Code Online (Sandbox Code Playgroud)

抢占式摘要身份验证设置

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

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

请参阅之前的答案以使用抢占式摘要身份验证。就我个人而言,考虑到可能遇到的复杂性和问题,我不建议将抢占式摘要身份验证与 RestTemplate 一起使用。使用抢占式摘要身份验证的主要动机是出于性能目的,因此除非您对每个请求进行大量调用,否则非抢占式摘要身份验证可能是更好的选择。


使用 RestTemplate 发送请求

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

示例 GET 请求

String response = restTemplate.getForObject(url, String.class);
JSONObject result = new JSONObject(response);
Run Code Online (Sandbox Code Playgroud)

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);
Run Code Online (Sandbox Code Playgroud)