精讲RestTemplate第9篇-如何通过HTTP Basic Auth认证
本文是精讲RestTemplate第9篇,前篇的blog访问地址如下:
- 精讲RestTemplate第1篇-在Spring或非Spring环境下如何使用
- 精讲RestTemplate第2篇-多种底层HTTP客户端类库的切换
- 精讲RestTemplate第3篇-GET请求使用方法详解
- 精讲RestTemplate第4篇-POST请求方法使用详解
- 精讲RestTemplate第5篇-DELETE、PUT等请求方法使用详解
- 精讲RestTemplate第6篇-文件上传下载与大文件流式下载
- 精讲RestTemplate第7篇-自定义请求失败异常处理
- 精讲RestTemplate第8篇-请求失败自动重试机制
服务提供方通常会通过一定的授权、鉴权认证逻辑来保护API接口。其中比较简单、容易实现的方式就是使用HTTP 的Basic Auth来实现接口访问用户的认证。我们本节就来为大家介绍一下,在服务端加入Basic Auth认证的情况下,该如何使用RestTemplate访问服务端接口。
一、HttpBasic认证原理说明

- 首先,HttpBasic模式要求传输的用户名密码使用Base64模式进行加密。如果用户名是
"admin",密码是“ admin”,则将字符串"admin:admin"使用Base64编码算法加密。加密结果可能是:YWtaW46YWRtaW4=。 - 然后,在Http请求中使用authorization作为一个HTTP请求头Header name,“Basic YWtaW46YWRtaW4=“作为Header的值,发送给服务端。(注意这里使用Basic+空格+加密串)
- 服务器在收到这样的请求时,到达BasicAuthenticationFilter过滤器,将提取“authorization”的Header值,并使用用于验证用户身份的相同算法Base64进行解码。
- 解码结果与登录验证的用户名密码匹配,匹配成功则可以继续过滤器后续的访问。
二、HTTP Basic Auth服务端实现
如果你想自己搭建一个服务端,那么如何为Spring Boot 服务添加Basic Auth认证?请参考我的另外一篇文章:《Spring Security系列之Http Basic Auth登录认证模式》 。
当然我们也可以不用自己去搭建服务端,给大家介绍一个提供免费在线的RESTful接口服务的网站:httpbin.com。这个网站为我们提供了Basic Auth认证测试服务接口。如果我们只是为了学习RestTemplate,直接用这个网站提供的服务就可以了。

浏览器访问地址:http://www.httpbin.org/#/Auth/get_basic_auth__user___passwd_ ,这个接口服务是通过OpenAPI(swagger)实现的,所以可以进行在线的访问测试。所以可以先通过页面操作测试一下,再开始下面学习使用RestTemplate访问服务端接口。
三、请求头方式携带认证信息
在HTTP请求头中携带Basic Auth认证的用户名和密码,具体实现参考下文代码注释:
@SpringBootTest
class BasicAuthTests {
@Resource
private RestTemplate restTemplate;
@Test
void testBasicAuth() {
//该url上携带用户名密码是httpbin网站测试接口的要求,
//真实的业务是不需要在url上体现basic auth用户名密码的
String url = "http://www.httpbin.org/basic-auth/admin/adminpwd";
//在请求头信息中携带Basic认证信息(这里才是实际Basic认证传递用户名密码的方式)
HttpHeaders headers = new HttpHeaders();
headers.set("authorization",
"Basic " +
Base64.getEncoder()
.encodeToString("admin:adminpwd".getBytes()));
//发送请求
HttpEntity<String> ans = restTemplate
.exchange(url,
HttpMethod.GET, //GET请求
new HttpEntity<>(null, headers), //加入headers
String.class); //body响应数据接收类型
System.out.println(ans);
}
}
测试用例执行成功,说明RestTemplate 正确的携带了Basic 认证信息,得到正常的响应结果:200。

四、拦截器方式携带认证信息
第三小节中的代码虽然实现了功能,但是不够好。因为每一次发送HTTP请求,我们都需要去组装HttpHeaders 信息,这样不好,造成大量的代码冗余。那么有没有一种方式可以实现可以一次性的为所有RestTemplate请求API添加Http Basic认证信息呢?答案就是:在RestTemplate Bean初始化的时候加入拦截器,以拦截器的方式统一添加Basic认证信息。
下面的代码结合注释去看,如果看不懂,需要去参考:精讲RestTemplate第2篇-多种底层HTTP客户端类库的切换
@Configuration
public class ContextConfig {
@Bean("OKHttp3")
public RestTemplate OKHttp3RestTemplate(){
RestTemplate restTemplate = new RestTemplate(getClientHttpRequestFactory());
//添加拦截器
restTemplate.getInterceptors().add(getCustomInterceptor());
return restTemplate;
}
//实现一个拦截器:使用拦截器为每一个HTTP请求添加Basic Auth认证用户名密码信息
private ClientHttpRequestInterceptor getCustomInterceptor(){
ClientHttpRequestInterceptor interceptor = (httpRequest, bytes, execution) -> {
httpRequest.getHeaders().set("authorization",
"Basic " +
Base64.getEncoder()
.encodeToString("admin:adminpwd".getBytes()));
return execution.execute(httpRequest, bytes);
};
return interceptor;
}
//这段代码是《第3节-底层HTTP客户端实现切换》的内容
private ClientHttpRequestFactory getClientHttpRequestFactory() {
int timeout = 100000;
OkHttp3ClientHttpRequestFactory clientHttpRequestFactory
= new OkHttp3ClientHttpRequestFactory();
clientHttpRequestFactory.setConnectTimeout(timeout);
return clientHttpRequestFactory;
}
}
在RestTemplate Bean初始化的时候加入拦截器之后,第三小节中的代码就可以省略HttpHeaders Basic Auth请求头携带信息的组装过程。发送请求,结果和第三小节中的效果是一样的。
五、进一步简化
上面的方式使用了拦截器,但仍然是我们自己来封装HTTP headers请求头信息。进一步的简化方法就是,Spring RestTemplate 已经为我们提供了封装好的Basic Auth拦截器,我们直接使用就可以了,不需要我们自己去实现拦截器。

下面的方法是在RestTemplate Bean实例化的时候使用RestTemplateBuilder,自带basicAuthentication。所以到这里拦截器也不需要了(实际底层代码实现仍然是拦截器,只是api层面不需要指定拦截器了)。

发送请求,结果和第三小节中的效果是一样的。
欢迎关注我的博客,里面有很多精品合集
- 本文转载注明出处(必须带连接,不能只转文字):字母哥博客。
觉得对您有帮助的话,帮我点赞、分享!您的支持是我不竭的创作动力! 。另外,笔者最近一段时间输出了如下的精品内容,期待您的关注。
- 《手摸手教你学Spring Boot2.0》
- 《Spring Security-JWT-OAuth2一本通》
- 《实战前后端分离RBAC权限管理系统》
- 《实战SpringCloud微服务从青铜到王者》
- 《VUE深入浅出系列》
精讲RestTemplate第9篇-如何通过HTTP Basic Auth认证的更多相关文章
- 精讲RestTemplate第10篇-使用代理作为跳板发送请求
本文是精讲RestTemplate第10篇,前篇的blog访问地址如下: 精讲RestTemplate第1篇-在Spring或非Spring环境下如何使用 精讲RestTemplate第2篇-多种底层 ...
- 精讲RestTemplate第2篇-多种底层HTTP客户端类库的切换
本文是精讲RestTemplate第2篇,前篇的blog访问地址如下: 精讲RestTemplate第1篇-在Spring或非Spring环境下如何使用 RestTemplate只是对其他的HTTP客 ...
- 精讲RestTemplate第3篇-GET请求使用方法详解
本文是精讲RestTemplate第3篇,前篇的blog访问地址如下: 精讲RestTemplate第1篇-在Spring或非Spring环境下如何使用 精讲RestTemplate第2篇-多种底层H ...
- 精讲RestTemplate第4篇-POST请求方法使用详解
本文是精讲RestTemplate第4篇,前篇的blog访问地址如下: 精讲RestTemplate第1篇-在Spring或非Spring环境下如何使用 精讲RestTemplate第2篇-多种底层H ...
- 精讲RestTemplate第4篇-DELETE、PUT等请求方法使用详解
本文是精讲RestTemplate第5篇,前篇的blog访问地址如下: 精讲RestTemplate第1篇-在Spring或非Spring环境下如何使用 精讲RestTemplate第2篇-多种底层H ...
- 精讲RestTemplate第6篇-文件上传下载与大文件流式下载
本文是精讲RestTemplate第6篇,前篇的blog访问地址如下: 精讲RestTemplate第1篇-在Spring或非Spring环境下如何使用 精讲RestTemplate第2篇-多种底层H ...
- 精讲RestTemplate第7篇-自定义请求失败异常处理
本文是精讲RestTemplate第7篇,前篇的blog访问地址如下: 精讲RestTemplate第1篇-在Spring或非Spring环境下如何使用 精讲RestTemplate第2篇-多种底层H ...
- 精讲RestTemplate第8篇-请求失败自动重试机制
本文是精讲RestTemplate第8篇,前篇的blog访问地址如下: 精讲RestTemplate第1篇-在Spring或非Spring环境下如何使用 精讲RestTemplate第2篇-多种底层H ...
- 精讲RestTemplate第1篇-在Spring或非Spring环境下如何使用
一.什么是 RestTemplate? RestTemplate是执行HTTP请求的同步阻塞式的客户端,它在HTTP客户端库(例如JDK HttpURLConnection,Apache HttpCo ...
随机推荐
- 最全JavaScript基础总结
JavaScript介绍 什么是JavaScript? Javascript是一门面向对象的,跨平台的脚本语言. JavaScript有什么特点? 解释性脚本语言 运行在浏览器(浏览器内核带有js解释 ...
- 服务端socket重用属性设置
初始化socket socket是一种系统资源,并不是每次初始化都一定成功,因此为了避免初始化失败,一般使用多次初始化的方式,如下所示: unsigned int times = 0x0; while ...
- [日常摘要] -- zookeeper篇
概览 设计目标 是将那些复杂且容易出错的分布式一致性服务封装起来,构成一个高效可靠的原语集,并以一系列简单易用的接口提供给用户使用 简介 是一个典型的分布式数据一致性解决方案,分布式应用程序可以基于Z ...
- Java中static、final和static final(final static)的区别(转)
大佬的总结(大赞!) final可以修饰:属性,方法,类,局部变量(方法中的变量) final修饰的属性的初始化可以在编译期,也可以在运行期,初始化后不能被改变. final修饰的属性跟具体对象有关, ...
- Presto性能调优的五大技巧
概述 Presto架构 Presto是一个分布式的查询引擎,本身并不存储数据,但是可以接入多种数据源,并且支持跨数据源的级联查询. Presto的架构分为: Coodinator:解析SQL语句,生成 ...
- vue学习(六) 事件修饰符 stop prevent capture self once
//html <div id="app"> <div @click="divHandler" style="height:150px ...
- 羞羞的Python模块包
目录 一.pip 二.pip常用命令 三.No module 'xxxxx' 四.写在最后 前言 写Python代码的时候,经常会遇到包的问题,但是都是遇到一次,搜索一次,解决了.下一次还是同样的 ...
- Django序列化组件Serializers详解
本文主要系统性的讲解django rest framwork 序列化组件的使用,基本看完可以解决工作中序列化90%的问题,写作参考官方文档https://www.django-rest-framewo ...
- linux下快速列出局域网中所有主机名(计算机名)的脚本
最近有列出局域网中所有主机名的需求(SMB协议里的),但是findsmb命令总是列不全,搜了搜网上也没什么现成的解决方案,于是自己写了个python脚本 脚本会扫描局域网arp表中所有ip,并尝试解析 ...
- PHP soundex() 函数
实例 计算 "Hello" 的 soundex 键: <?php高佣联盟 www.cgewang.com$str = "Hello";echo sound ...