有道无术,术尚可求,有术无道,止于术。

资料整理来自网络

文章目录

  • BasicAuthRequestInterceptor
    • Basic 认证
    • 使用案例
    • 源码
  • OAuth2FeignRequestInterceptor
    • 源码分析
    • 应用场景
    • 使用案例

BasicAuthRequestInterceptor

BasicAuthRequestInterceptor翻译过来就是 Basic 认证请求拦截器。

Basic 认证

Basic认证是一种较为简单的HTTP认证方式,客户端通过明文(Base64编码格式)传输用户名和密码到服务端进行认证,通常需要配合HTTPS来保证信息传输的安全。

比如Security 就支持这种方式,在发送认证请求时,按照以下格式:

// 请求头Authorization 添加Basic 认证信息
Authorization: Basic 用户名:密码Base64编码格式

使用案例

首先注入一个BasicAuthRequestInterceptor

    @BeanBasicAuthRequestInterceptor basicAuthRequestInterceptor(){return new BasicAuthRequestInterceptor("zhangsan","123456");}

然后使用Feign调用远程服务,可以在日志中看到在消息头中添加了Basic认证信息:

源码

源码也很简单,就是将用户名密码,经过编码后放入到消息头中:

public class BasicAuthRequestInterceptor implements RequestInterceptor {private final String headerValue;public BasicAuthRequestInterceptor(String username, String password) {this(username, password, Util.ISO_8859_1);}public BasicAuthRequestInterceptor(String username, String password, Charset charset) {Util.checkNotNull(username, "username", new Object[0]);Util.checkNotNull(password, "password", new Object[0]);this.headerValue = "Basic " + base64Encode((username + ":" + password).getBytes(charset));}private static String base64Encode(byte[] bytes) {return Base64.encode(bytes);}public void apply(RequestTemplate template) {template.header("Authorization", new String[]{this.headerValue});}
}

OAuth2FeignRequestInterceptor

OAuth2FeignRequestInterceptor属于spring-cloud-security包,可以看到都标记为了过时,这是因为security-oauth2已经快停止维护,换了新的项目,已经正式发布。

源码分析

先按照顺序看下这个拦截器的处理逻辑,可以看到就是使用一个OAuth2 客户端上下文对象来存储令牌信息,每次请求时,会去校验当前上下文中令牌是否过期或不存在,不可用时,调用配置的认证中心获取令牌,然后将令牌放入到请求头中。

public class OAuth2FeignRequestInterceptor implements RequestInterceptor {public static final String BEARER = "Bearer";public static final String AUTHORIZATION = "Authorization";private final OAuth2ClientContext oAuth2ClientContext;private final OAuth2ProtectedResourceDetails resource;private final String tokenType;private final String header;private AccessTokenProvider accessTokenProvider;public OAuth2FeignRequestInterceptor(OAuth2ClientContext oAuth2ClientContext, OAuth2ProtectedResourceDetails resource) {this(oAuth2ClientContext, resource, "Bearer", "Authorization");}public OAuth2FeignRequestInterceptor(OAuth2ClientContext oAuth2ClientContext, OAuth2ProtectedResourceDetails resource, String tokenType, String header) {this.accessTokenProvider = new AccessTokenProviderChain(Arrays.asList(new AuthorizationCodeAccessTokenProvider(), new ImplicitAccessTokenProvider(), new ResourceOwnerPasswordAccessTokenProvider(), new ClientCredentialsAccessTokenProvider()));this.oAuth2ClientContext = oAuth2ClientContext;this.resource = resource;this.tokenType = tokenType;this.header = header;}public void apply(RequestTemplate template) {// 5. 将Oauth2 令牌放入到消息头中。template.header(this.header, new String[0]);template.header(this.header, new String[]{this.extract(this.tokenType)});}protected String extract(String tokenType) {OAuth2AccessToken accessToken = this.getToken();return String.format("%s %s", tokenType, accessToken.getValue());}public OAuth2AccessToken getToken() {// 1. 获取 OAuth2令牌 OAuth2AccessToken accessToken = this.oAuth2ClientContext.getAccessToken();if (accessToken == null || accessToken.isExpired()) {// 2. 如果令牌不存在或者过期,重新获取一个令牌try {accessToken = this.acquireAccessToken();} catch (UserRedirectRequiredException var5) {this.oAuth2ClientContext.setAccessToken((OAuth2AccessToken)null);String stateKey = var5.getStateKey();if (stateKey != null) {Object stateToPreserve = var5.getStateToPreserve();if (stateToPreserve == null) {stateToPreserve = "NONE";}this.oAuth2ClientContext.setPreservedState(stateKey, stateToPreserve);}throw var5;}}return accessToken;}protected OAuth2AccessToken acquireAccessToken() throws UserRedirectRequiredException {// 3. 创建一个获取令牌的请求对象AccessTokenRequest tokenRequest = this.oAuth2ClientContext.getAccessTokenRequest();if (tokenRequest == null) {throw new AccessTokenRequiredException("Cannot find valid context on request for resource '" + this.resource.getId() + "'.", this.resource);} else {String stateKey = tokenRequest.getStateKey();if (stateKey != null) {tokenRequest.setPreservedState(this.oAuth2ClientContext.removePreservedState(stateKey));}OAuth2AccessToken existingToken = this.oAuth2ClientContext.getAccessToken();if (existingToken != null) {this.oAuth2ClientContext.setAccessToken(existingToken);}// 4. 使用令牌提供者获取一个令牌OAuth2AccessToken obtainableAccessToken = this.accessTokenProvider.obtainAccessToken(this.resource, tokenRequest);if (obtainableAccessToken != null && obtainableAccessToken.getValue() != null) {this.oAuth2ClientContext.setAccessToken(obtainableAccessToken);return obtainableAccessToken;} else {throw new IllegalStateException(" Access token provider returned a null token, which is illegal according to the contract.");}}}public void setAccessTokenProvider(AccessTokenProvider accessTokenProvider) {this.accessTokenProvider = accessTokenProvider;}
}

应用场景

当某个服务是Oauth 2的资源服务器,第三方使用Feign 去访问时,需要携带Oauth 2令牌去访问,这个时候就可以使用当前拦截器添加Oauth 2认证。

使用案例

场景:现在我们有一个微服务项目,采用Oauth 2认证方式,这个时候有个第三方,想通过Feign 调用我们的资源服务器,这个时候就可以让第三方集成我们的 Oauth 2客户端。

首先需要引入依赖:

        <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-security</artifactId></dependency>

然后注入 一个 Oauth 2客户端,这里演示使用密码模式。

    @BeanOAuth2ClientContext oAuth2ClientContext(){return new DefaultOAuth2ClientContext();}@BeanOAuth2FeignRequestInterceptor oAuth2FeignRequestInterceptor(OAuth2ClientContext oAuth2ClientContext, ResourceOwnerPasswordResourceDetails resourceOwnerPasswordResourceDetails){return new OAuth2FeignRequestInterceptor(oAuth2ClientContext,resourceOwnerPasswordResourceDetails);}@BeanResourceOwnerPasswordResourceDetails resourceOwnerPasswordResourceDetails(){ResourceOwnerPasswordResourceDetails resourceOwnerPasswordResourceDetails = new ResourceOwnerPasswordResourceDetails();resourceOwnerPasswordResourceDetails.setUsername("hnmqet");resourceOwnerPasswordResourceDetails.setPassword("123456");resourceOwnerPasswordResourceDetails.setClientId("ZD");resourceOwnerPasswordResourceDetails.setClientSecret("123456");resourceOwnerPasswordResourceDetails.setAccessTokenUri("http://192.168.58.1:21101/oauth/token");return resourceOwnerPasswordResourceDetails;}

测试,可以看到该拦截器,最终会调用OAuth2AccessTokenSupport去远程获取令牌,然后放在消息头中去发送Feign 请求。

Spring Cloud Open Feign系列【23】OAuth2FeignRequestInterceptor、BasicAuthRequestInterceptor拦截器解析相关推荐

  1. Spring Cloud Open Feign系列【11】Feign 编码解码器Encoder和Decoder源码分析

    文章目录 概述 接口及相关实现类 Encoder 接口 Decoder接口 执行流程源码分析 1. 项目结构改造 2. 编码器流程 3. 解码器流程 4. 异常解码处理流程 5. 404异常特殊处理 ...

  2. Spring Cloud微服务系列文,服务调用框架Feign

    之前博文的案例中,我们是通过RestTemplate来调用服务,而Feign框架则在此基础上做了一层封装,比如,可以通过注解等方式来绑定参数,或者以声明的方式来指定请求返回类型是JSON.    这种 ...

  3. Spring Cloud 2.x系列之Feign整合断路器监控Hystrix Dashboard

    SVN多版本库环境的搭建 OAuth 2.0是什么?看这篇文章就够了. 前端 Java Python等资源合集大放送 Ribbon可以整合整合断路器监控Hystrix Dashboard,Feign也 ...

  4. routing zuul_金三银四跳槽季快到了:送上Spring cloud全家桶系列之Zuul

    一.前言 金三银四跳槽季快到了:送上Spring cloud全家桶系列之Eureka 金三银四跳槽季快到了:送上Spring cloud全家桶系列之Feign 金三银四跳槽季快到了:送上Spring ...

  5. Spring Cloud(四):Spring Cloud Alibaba Feign Dubbo

    扩展点 RequestInterceptor#apply 扩展点 feign.Client#execute spring cloud dubbo 调用 RPC RPC 全称是 Remote Proce ...

  6. Spring Cloud微服务系列-Eureka Client源码解析(二)

    导语   上一篇博客中介绍了关于Eureka Client源码的基础部分,如果对于基础部分不是很了解的读者可以点击下面的连接进入到源码分析一中,从头开始学习 Spring Cloud微服务系列 Dis ...

  7. 【Spring Cloud 基础设施搭建系列】Spring Cloud Demo项目 将微服务运行在Docker上

    文章目录 将微服务运行在Docker上 使用Maven插件构建Docker镜像 使用Maven插件读取Dockerfile进行构建 将插件绑定在某个phase执行 参考 源代码 将微服务运行在Dock ...

  8. Spring Cloud (Eureka,Feign,Hystrix整合)

    Spring Cloud(Eureka,Feign,Hystrix整合) Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智能路由,微代 ...

  9. spring cloud 快速上手系列 -> 02-配置中心 Config -> 022-Config客户端

    spring cloud 快速上手系列 系列说明:快速上手,一切从简,搭建一个简单的微服务框架,让新手可以在这个基础框架上做各种学习.研究. 02-配置中心 Config 022-Config客户端 ...

最新文章

  1. python 在地图上的散点图-Matplotlib中的散点图等高线
  2. python的turtle画曲线_python的turtle模块画折线图
  3. 解决Windows 8系统假死的方法
  4. [NHibernate]集合类(Collections)映射
  5. C语言佛,佛大c语言毕业前补考.doc
  6. win11桌面图标模糊怎么办 windows11桌面图标模糊的解决方法
  7. 孔子做人精要,看完启发很多
  8. “钱妈妈”平台犯罪嫌疑人被抓捕 涉嫌非法吸收公众存款
  9. Pt100铂电阻测温电路设计——
  10. 【H2O系列001】H2O概述
  11. vs2013右键菜单 0xC0000005: 读取位置 0x00000004 时发生访问冲突
  12. openpyxl 获取worksheet颜色
  13. 记录一下线上高并发情况下 SimpleDateFormat 出现异常问题【项目】
  14. Qt在设计ui界面时,在控件中输入中文,会自动变成英文字母,解决方案
  15. idea设置单行注释格式(包括配置文件)
  16. 华为防火墙实现双机热备配置详解
  17. 黄**解说的各种版本
  18. PHP复习_封装万能的PDO类
  19. 计算机会计模块考试,会计电算化考试
  20. win10系统ipv6服务器地址,Win10关闭iPv6地址方法

热门文章

  1. “人工智能发展现状”
  2. c语言kbhit函数头文件,有没有办法在标准C中替换kbhit()和getch()函数?
  3. 内推 | 【国企】中国人寿-数据管理与数据分析/成都
  4. 【BZOJ3168】[Heoi2013]钙铁锌硒维生素 高斯消元求矩阵的逆+匈牙利算法
  5. C++STL之初识容器和迭代器
  6. c语言试题及答案解析,C语言期末考试题(卷)(含答案解析).doc
  7. 实时日志/数据库采集处理,实时用户行为属性个人总结
  8. 学习退款数据分析思路
  9. 【狂神说:秦疆】SpringMVC笔记
  10. windows,打印机无打印任务,仍不断打印