RestTemplate with Digest Authentication – 采用Digest认证的RestTemplate

最后修改: 2013年 8月 4日

1. Overview

1.概述

This article will show how to configure the Spring RestTemplate to consume a service secured with Digest Authentication.

本文将展示如何配置Spring RestTemplate,以消费使用Digest Authentication的服务

Similar to Basic Authentication, once Digest auth is set in the template, the client will be able to go through the necessary security steps and get the information needed for the Authorization header:

与基本认证类似,一旦在模板中设置了Digest auth,客户端将能够通过必要的安全步骤,获得Authorization头所需的信息。

Authorization: Digest 
    username="user1",
    realm="Custom Realm Name",
    nonce="MTM3NTYwOTA5NjU3OTo5YmIyMjgwNTFlMjdhMTA1MWM3OTMyMWYyNDY2MGFlZA==",
    uri="/spring-security-rest-digest-auth/api/foos/1", 
    ....

With this data, the server can correctly authenticate the request and return the 200 OK response.

有了这些数据,服务器可以正确地验证请求并返回200 OK的响应。

2. Setup the RestTemplate

2.设置RestTemplate

The RestTemplate needs to be declared as a bean in the Spring context – this is simple enough either in XML or plain Java, using the @Bean annotation:

RestTemplate需要在Spring上下文中被声明为一个bean–这在XML或普通Java中都很简单,使用@Bean注解即可。

import org.apache.http.HttpHost;
import com.baeldung.client.HttpComponentsClientHttpRequestFactoryDigestAuth;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration
public class ClientConfig {

    @Bean
    public RestTemplate restTemplate() {
        HttpHost host = new HttpHost("localhost", 8080, "http");
        CloseableHttpClient client = HttpClientBuilder.create().
          setDefaultCredentialsProvider(provider()).useSystemProperties().build();
        HttpComponentsClientHttpRequestFactory requestFactory = 
          new HttpComponentsClientHttpRequestFactoryDigestAuth(host, client);

        return new RestTemplate(requestFactory);;
    }
    
    private CredentialsProvider provider() {
        CredentialsProvider provider = new BasicCredentialsProvider();
        UsernamePasswordCredentials credentials = 
          new UsernamePasswordCredentials("user1", "user1Pass");
        provider.setCredentials(AuthScope.ANY, credentials);
        return provider;
    }
}

Most of the configuration of the digest access mechanism is done in the custom implementation of the client http request factory injected into the template – HttpComponentsClientHttpRequestFactoryDigestAuth.

摘要访问机制的大部分配置是在注入模板的客户端http请求工厂的自定义实现中完成的 – HttpComponentsClientHttpRequestFactoryDigestAuth

Note that we are now pre-configuring the template with the credentials that have access to the secured API.

请注意,我们现在是用可以访问安全API的凭证来预配置模板。

3. Configure Digest Authentication

3.配置摘要验证

We are going to leverage the support introduced in Spring 3.1 for the current HttpClient 4.x – namely the HttpComponentsClientHttpRequestFactory – by extending and configuring it.

我们将利用Spring 3.1中引入的对当前HttpClient 4.x的支持–即HttpComponentsClientHttpRequestFactory–通过扩展和配置它。

We’re mainly going to configure the HttpContext and hook up our custom logic for Digest Authentication:

我们主要是要配置HttpContext并为Digest Authentication挂上我们的自定义逻辑。

import java.net.URI;
import org.apache.http.HttpHost;
import org.apache.http.client.AuthCache;
import org.apache.http.client.protocol.ClientContext;
import org.apache.http.impl.auth.DigestScheme;
import org.apache.http.impl.client.BasicAuthCache;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HttpContext;
import org.springframework.http.HttpMethod;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;

public class HttpComponentsClientHttpRequestFactoryDigestAuth 
  extends HttpComponentsClientHttpRequestFactory {

    HttpHost host;

    public HttpComponentsClientHttpRequestFactoryDigestAuth(HttpHost host, HttpClient httpClient) {
        super(httpClient);
        this.host = host;
    }

    @Override
    protected HttpContext createHttpContext(HttpMethod httpMethod, URI uri) {
        return createHttpContext();
    }

    private HttpContext createHttpContext() {
        // Create AuthCache instance
        AuthCache authCache = new BasicAuthCache();
        // Generate DIGEST scheme object, initialize it and add it to the local auth cache
        DigestScheme digestAuth = new DigestScheme();
        // If we already know the realm name
        digestAuth.overrideParamter("realm", "Custom Realm Name");
        authCache.put(host, digestAuth);

        // Add AuthCache to the execution context
        BasicHttpContext localcontext = new BasicHttpContext();
        localcontext.setAttribute(ClientContext.AUTH_CACHE, authCache);
        return localcontext;
    }
}

Now, the RestTemplate can simply be injected and used in a test:

现在,RestTemplate可以简单地被注入并用于测试中。

@Test
public void whenSecuredRestApiIsConsumed_then200OK() {
    String uri = "http://localhost:8080/spring-security-rest-digest-auth/api/foos/1";
    ResponseEntity<Foo> entity = restTemplate.exchange(uri, HttpMethod.GET, null, Foo.class);
    System.out.println(entity.getStatusCode());
}

To illustrate the full configuration process, this test also sets up the user credentials – user1 and user1Pass. This part should, of course, be done only once and outside the test itself.

为了说明完整的配置过程,这个测试还设置了用户凭证–user1user1Pass。当然,这部分应该只做一次,而且是在测试本身之外

4. Maven Dependencies

4.Maven的依赖性

The required Maven Dependencies for the RestTemplate and the HttpClient library are:

RestTemplate和HttpClient库所需的Maven依赖项是。

<dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-webmvc</artifactId>
   <version>5.2.8.RELEASE</version>
</dependency>

<dependency>
   <groupId>org.apache.httpcomponents</groupId>
   <artifactId>httpclient</artifactId>
   <version>4.3.5</version>
</dependency>

5. Conclusion

5.结论

This tutorial showed how to set up and configure the Rest Template so that it can consume an application secured with Digest authentication. The REST API itself needs to be configured with the digest security mechanism.

本教程展示了如何设置和配置Rest模板,以使其能够消费具有Digest认证的应用程序。REST API本身需要配置digest安全机制。

The implementation can be found in the example GitHub project – this is a Maven-based project, so it should be easy to import and run as it is.

该实现可以在GitHub 示例项目中找到–这是一个基于Maven的项目,所以应该很容易导入并按原样运行。