前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >RestTemplate进阶:打开Basic Authorization的正确zishi,你知道吗<( ̄︶ ̄)↗[GO!]

RestTemplate进阶:打开Basic Authorization的正确zishi,你知道吗<( ̄︶ ̄)↗[GO!]

作者头像
烟雨平生
发布2023-03-07 14:47:28
6180
发布2023-03-07 14:47:28
举报
文章被收录于专栏:数字化之路数字化之路
生活就是练习.柬埔寨

原文链接: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头会长这个样子:

代码语言:javascript
复制
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==

2. 配置RestTemplate

通过简单地将 RestTemplate类声明为一个 bean,就可以将其注入到Spring上下文;然而,要注入一个携带 Basic身份认证信息的 RestTemplate,就需要一些额外的自定义配置,因此我们将使用Spring FactoryBean来实现更大的灵活性,而不是直接声明 bean。这个工厂类将在初始化时创建和配置 RestTemplate

代码语言:javascript
复制
@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));
    }
}

hostport值应该依赖于环境——即开发环境、测试环境、预发布环境、生产环境下的值是不同的。在Spring中,可以通过 properties文件来管理这些值。

3.手动管理AuthorizationHTTP头

对于 Basic身份认证来说,创建Authorization头也比较简单,即只需几行代码就可以完成:

代码语言:javascript
复制
    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.自动管理AuthorizationHTTP头

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方法:

代码语言:javascript
复制
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身份认证;

代码语言:javascript
复制
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库都是必需的:

代码语言:javascript
复制
<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的项目,因此很容易导入和运行。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-10-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 的数字化之路 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 目录
  • 1. 概览
  • 2. 配置RestTemplate
  • 3.手动管理AuthorizationHTTP头
  • 4.自动管理AuthorizationHTTP头
  • 5. Maven依赖
  • 6. 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档