原文链接:https://www.baeldung.com/how-to-use-resttemplate-with-basic-authentication-in-spring
作者: Eugen Paraschiv
译者: helloworldtang
目录
- 1. 概览
- 2. 在Spring中配置RestTemplate
- 3. 手动管理
Authorization
HTTP头 - 4. 自动管理
Authorization
HTTP头 - 5. Maven依赖
- 6.总结
1. 概览
本文将展示如何使用Spring RestTemplate
来消费一个需要 Basic
身份认证的RESTful服务。
一旦为RestTemplate
配置了用于 Basic
身份认证的HTTP头,每个请求都会携带用于身份认证的完整凭证。凭证信息将按照 Basic
身份认证规范进行编码并存放到一个名为Authorization的HTTP头中。一个Authorization HTTP头会长这个样子:
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
2. 配置RestTemplate
通过简单地将 RestTemplate
类声明为一个 bean
,就可以将其注入到Spring上下文;然而,要注入一个携带 Basic
身份认证信息的 RestTemplate
,就需要一些额外的自定义配置,因此我们将使用Spring FactoryBean
来实现更大的灵活性,而不是直接声明 bean
。这个工厂类将在初始化时创建和配置 RestTemplate
:
@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
文件来管理这些值。
3.手动管理Authorization
HTTP头
对于 Basic
身份认证来说,创建Authorization头也比较简单,即只需几行代码就可以完成:
HttpHeaders createHeaders(String username, String password) {
return new HttpHeaders() {
{
String auth = username ":" password;
byte[] originAuth = auth.getBytes(Charset.forName("US-ASCII"));
byte[] encodedAuth = Base64.encodeBase64(originAuth);
String authHeader = "Basic " new String(encodedAuth);
set("Authorization", authHeader);
}
};
}
那么,发送请求也变得同样简单:
代码语言:javascript复制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中,通过
HttpComponentsClientHttpRequestFactory
引入了对HttpClient 4.x的支持(在JIRA SPR-6180中添加的支持) - 在Spring 4.0中,通过
HttpComponentsAsyncClientHttpRequestFactory
引入对异步请求的支持
现在,咱们开始使用HttpClient 4和Spring 4来配置一些东西。
到目前为止,RestTemplate
需要一个HttpRequestFactory
——一个支持 Basic
身份认证的工厂类。然而,直接使用现有的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
时,就内置了Basic
身份认证信息。这你也看到了,使用HttpClient 4.x进行抢占式Basic
身份认证是有点负担:缓存身份认证信息,并且建立这个身份认证缓存的过程也必须手动配置,并且非常不直观的。
万事俱备—— RestTemplate
现在可以通过添加BasicAuthorizationInterceptor
来支持Basic
身份认证;
restTemplate.getInterceptors().add(
new BasicAuthorizationInterceptor("username", "password"));
那么,具体的请求代码如下所示:
代码语言:javascript复制restTemplate.exchange(
"http://localhost:8082/spring-security-rest-basic-auth/api/foos/1",
HttpMethod.GET, null, Foo.class);
如果想了解如何保护REST服务的更多信息,请移步这篇。
5. Maven依赖
下面的Maven依赖项对于RestTemplate
本身和HttpClient
库都是必需的:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.0.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.3</version>
</dependency>
另外,如果通过手动生成Authorization HTTP头,也可以使用下面这个库来完成编码操作:
代码语言:javascript复制<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.10</version>
</dependency>
你可以在Maven仓库发现最新的版本。
6. 总结
尽管Apache HttpClient的3.x开发分支已经停止更新,并且Spring对这个版本的支持也已经被完全废弃了,但是在 RestTemplate
和安全性上找到的大部分信息仍然不能解释当前HttpClient 4.x发行版中的一些设计。本文尝试通过循序渐进的方式来解读如何使用RestTemplate
来配置 Basic
身份认证以及如何使用它来消费一个受保护的REST API来改变这种情况。
如果想写出更好的代码,或者想了解HTTP客户端以及用到的RESTful服务的实现,请查看Github上的项目。 这是一个基于Maven的项目,因此很容易导入和运行。