1. 概述

本文将展示如何 配置 Spring 的 RestTemplate 来消费受 Digest 认证保护的服务

与 Basic 认证类似,一旦在模板中设置好 Digest 认证,客户端就能自动完成必要的安全步骤,生成所需的 Authorization 头信息:

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

有了这些数据,服务器就能正确认证请求并返回 200 OK 响应。

2. 配置 RestTemplate

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;
    }
}

Digest 认证机制的大部分配置都在注入模板的自定义客户端请求工厂实现中完成——即 HttpComponentsClientHttpRequestFactoryDigestAuth

⚠️ 注意:我们预先配置了能访问受保护 API 的凭证。

3. 配置 Digest 认证

我们将利用 Spring 3.1 对 HttpClient 4.x 的支持——即 HttpComponentsClientHttpRequestFactory——通过扩展并配置它来实现。

主要工作是配置 HttpContext 并接入我们的自定义 Digest 认证逻辑:

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() {
        // 创建 AuthCache 实例
        AuthCache authCache = new BasicAuthCache();
        // 生成 DIGEST scheme 对象,初始化并添加到本地 auth cache
        DigestScheme digestAuth = new DigestScheme();
        // 如果已知 realm 名称
        digestAuth.overrideParamter("realm", "Custom Realm Name");
        authCache.put(host, digestAuth);

        // 将 AuthCache 添加到执行上下文
        BasicHttpContext localcontext = new BasicHttpContext();
        localcontext.setAttribute(ClientContext.AUTH_CACHE, authCache);
        return localcontext;
    }
}

现在 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());
}

✅ 为完整展示配置过程,测试中设置了用户凭证(user1user1Pass)。这部分当然应该只执行一次且在测试外完成

4. Maven 依赖

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. 总结

本教程展示了如何设置和 配置 RestTemplate 以消费受 Digest 认证保护的应用。REST API 本身需要配置 Digest 安全机制

完整实现可在 GitHub 示例项目 中找到——这是一个基于 Maven 的项目,可以直接导入运行。


原始标题:RestTemplate with Digest Authentication