概述
在这个教程中,我们将学习如何使用Spring的RestTemplate
来消费带有基本身份验证的RESTful服务。
一旦我们在模板中设置了基本身份验证,每次请求都会预先包含执行身份验证过程所需的完整凭据。这些凭据会被编码,并根据基本身份验证方案的规范使用Authorization
HTTP头。一个例子看起来像这样:
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
TestRestTemplate介绍
This article explores the Spring Boot TestRestTemplate. It can be treated as a follow-up of The Guide to RestTemplate, which we firmly recommend to read before focusing on TestRestTemplate. TestRestTemplate can be considered as an attractive alternative of RestTemplate.
Spring Restemplate错误处理
In this short tutorial, we’ll discuss how to implement and inject the ResponseErrorHandler interface in a RestTemplate instance to gracefully handle the HTTP errors returned by remote APIs.
2. 设置RestTemplate
我们可以通过简单地在Spring上下文中声明一个bean来初始化RestTemplate
;然而,为了设置带有**基本身份验证的RestTemplate
**,我们需要手动干预。因此,我们不会直接声明bean,而是使用Spring的FactoryBean
以增加灵活性。这个FactoryBean
会在初始化时创建并配置模板:
@Component
public class RestTemplateFactory
implements FactoryBean<RestTemplate>, InitializingBean {
private RestTemplate restTemplate;
public RestTemplate getObject() {
return restTemplate;
}
public Class<RestTemplate> getObjectType() {
return RestTemplate.class;
}
public boolean isSingleton() {
return true;
}
public void afterPropertiesSet() {
HttpHost host = new HttpHost("localhost", 8082, "http");
restTemplate = new RestTemplate(
new HttpComponentsClientHttpRequestFactoryBasicAuth(host));
}
}
host
和port
值应该依赖于环境,以便客户端可以根据集成测试和生产环境定义不同的值。这些值可以通过Spring对properties文件的一流支持进行管理:使用Properties配置Spring项目。
3. 手动管理Authorization HTTP头
对于基本身份验证,我们很容易创建Authorization
头,所以我们可以手动编写几行代码来实现:
HttpHeaders createHeaders(String username, String password){
return new HttpHeaders() {{
String auth = username + ":" + password;
byte[] encodedAuth = Base64.encodeBase64(
auth.getBytes(Charset.forName("US-ASCII")) );
String authHeader = "Basic " + new String( encodedAuth );
set( "Authorization", authHeader );
}};
}
发送请求同样简单:
restTemplate.exchange
(uri, HttpMethod.POST, new HttpEntity<T>(createHeaders(username, password)), clazz);
4. 自动管理Authorization HTTP头
Spring 3.0、3.1以及现在的4.x都有对Apache HTTP库的良好支持:
- 在Spring 3.0中,
CommonsClientHttpRequestFactory
与现已过时的HttpClient 3.x
集成。 - Spring 3.1引入了对当前
HttpClient 4.x
的支持,通过HttpComponentsClientHttpRequestFactory
(添加支持于JIRA SPR-6180)。 - Spring 4.0通过
HttpComponentsAsyncClientHttpRequestFactory
引入了异步支持。
让我们开始使用HttpClient 4和Spring 4进行设置。
RestTemplate
需要一个支持基本身份验证的HTTP请求工厂。然而,直接使用现有的HttpComponentsClientHttpRequestFactory
可能会很困难,因为RestTemplate
的设计没有很好地支持HttpContext
,这是解决问题的关键部分。因此,我们需要子类化HttpComponentsClientHttpRequestFactory
并重写createHttpContext
方法:
public class HttpComponentsClientHttpRequestFactoryBasicAuth
extends HttpComponentsClientHttpRequestFactory {
HttpHost host;
public HttpComponentsClientHttpRequestFactoryBasicAuth(HttpHost host) {
super();
this.host = host;
}
protected HttpContext createHttpContext(HttpMethod httpMethod, URI uri) {
return createHttpContext();
}
private HttpContext createHttpContext() {
AuthCache authCache = new BasicAuthCache();
BasicScheme basicAuth = new BasicScheme();
authCache.put(host, basicAuth);
BasicHttpContext localcontext = new BasicHttpContext();
localcontext.setAttribute(HttpClientContext.AUTH_CACHE, authCache);
return localcontext;
}
}
我们在创建HttpContext
时构建了基本身份验证支持。如你所见,使用HttpClient 4.x进行预授权的基本身份验证对我们来说有些麻烦。认证信息被缓存,手动设置这个认证缓存既繁琐又不直观。
现在一切就绪,RestTemplate
只需添加一个BasicAuthorizationInterceptor
即可支持基本身份验证方案:
restTemplate.getInterceptors().add(
new BasicAuthorizationInterceptor("username", "password"));
然后发送请求:
restTemplate.exchange(
"http://localhost:8082/spring-security-rest-basic-auth/api/foos/1",
HttpMethod.GET, null, Foo.class);
有关如何安全地保护REST服务本身的深入讨论,请参阅这篇文章。
5. Maven依赖
RestTemplate
本身和HttpClient库需要以下Maven依赖:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>6.0.13</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents.client5</groupId>
<artifactId>httpclient5</artifactId>
<version>5.2.1</version>
</dependency>
如果手动构造HTTP Authorization
头,我们还需要一个额外的库来支持编码支持:
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.10</version>
</dependency>
可以在Maven仓库找到最新版本:spring-webmvc,httpclient5和commons-codec。
6. 结论
关于RestTemplate
和安全性方面的许多信息仍然没有考虑到当前的HttpClient 4.x版本,尽管3.x分支已经过时,Spring对这个版本的支持已完全弃用。在这个文章中,我们试图通过详细讲解如何设置带有RestTemplate
的基本身份验证并使用它来消费一个受保护的REST API来改变这种情况。
要深入了解本文中的代码示例之外的消费者实现和实际RESTful服务,请查看GitHub上的项目:github.com/eugenp/tutorials/tree/master/spring-security-modules/spring-security-web-rest-basic-auth。
这是一个基于Maven的项目,可以直接导入并运行。