Spring Cloud OAuth 实现微服务内部Token传递的源码解析
背景分析
1.客户端携带认证中心发放的token,请求资源服务器A(Spring Security OAuth 发放Token 源码解析)
2.客户端携带令牌直接访问资源服务器,资源服务器通过对token 的校验 (Spring Cloud OAuth2 资源服务器CheckToken 源码解析 ) 判断用户的合法性,并保存到上下文中
3.A服务接口接收到请求,需要通过Feign或者其他RPC框架调用B服务来组装返回数据
本文主要来探讨第三部 A --> B ,token 自定维护的源码实现
如何实现token 传递
配置OAuth2FeignRequestInterceptor 即可
此类是Feign 的拦截器实现
@Bean
@ConditionalOnProperty("security.oauth2.client.client-id")
public RequestInterceptor oauth2FeignRequestInterceptor(OAuth2ClientContext oAuth2ClientContext,
OAuth2ProtectedResourceDetails resource,) {
return new OAuth2FeignRequestInterceptor(oAuth2ClientContext, resource);
}
源码解析
获取上下文中的token ,组装到请求头
public class OAuth2FeignRequestInterceptor implements RequestInterceptor {
// 给请求增加 token
@Override
public void apply(RequestTemplate template) {
template.header(header, extract(tokenType));
}
protected String extract(String tokenType) {
OAuth2AccessToken accessToken = getToken();
return String.format("%s %s", tokenType, accessToken.getValue());
}
// 从spring security 上下文中获取token
public OAuth2AccessToken getToken() {
OAuth2AccessToken accessToken = oAuth2ClientContext.getAccessToken();
if (accessToken == null || accessToken.isExpired()) {
try {
accessToken = acquireAccessToken();
}
}
return accessToken;
}
}
再来看AccessTokenContextRelay, 上下文token 中转器.非常简单从上下文获取认证信息得到把 token 放到上下文
public class AccessTokenContextRelay {
private OAuth2ClientContext context;
public AccessTokenContextRelay(OAuth2ClientContext context) {
this.context = context;
}
public boolean copyToken() {
if (context.getAccessToken() == null) {
Authentication authentication = SecurityContextHolder.getContext()
.getAuthentication();
if (authentication != null) {
Object details = authentication.getDetails();
if (details instanceof OAuth2AuthenticationDetails) {
OAuth2AuthenticationDetails holder = (OAuth2AuthenticationDetails) details;
String token = holder.getTokenValue();
DefaultOAuth2AccessToken accessToken = new DefaultOAuth2AccessToken(
token);
String tokenType = holder.getTokenType();
if (tokenType != null) {
accessToken.setTokenType(tokenType);
}
context.setAccessToken(accessToken);
return true;
}
}
}
return false;
}
}
什么时候执行中转,oauth2 资源服务器非常简单暴力,加了个拦截器给转发。
源码非常简单
谈谈spring security oauth 实现的问题
1、当请求上下文没有Token,如果调用feign 会直接,这个OAuth2FeignRequestInterceptor 肯定会报错,因为上下文copy 失败
2、如果设置线程隔离,这里也会报错。导致安全上下问题传递不到子线程中。
3、强制使用拦截器去处理 token 转发到这里上下文,使用的业务场景只有这里,影响性能高
这三个问题,大家在使用的过程中一定会遇到
自定义OAuth2FeignRequestInterceptor
通过外部条件是否执行token中转
public void apply(RequestTemplate template) {
Collection<String> fromHeader = template.headers().get(SecurityConstants.FROM);
if (CollUtil.isNotEmpty(fromHeader) && fromHeader.contains(SecurityConstants.FROM_IN)) {
return;
}
accessTokenContextRelay.copyToken();
if (oAuth2ClientContext != null
&& oAuth2ClientContext.getAccessToken() != null) {
super.apply(template);
}
}
手动调用accessTokenContextRelay的copy,当然需要覆盖原生oauth 客户端的配置
项目参考:https://gitee.com/log4j/pig
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
解决方案:如何防止数据重复插入?
目录 1.为啥要解决数据重复插入? 2.解决方案实战 3.可落地小总结 一、为啥要解决数据重复插入? 问题起源,微信小程序抽风 wx.request() 重复请求服务器提交数据。后端服务也很简单,伪代码如下: class SignLogService { public void saveSignLog(SignLogDO log) { // 简单插入做记录 SignLogDAO.insert(log); }} 发现数据库会存在重复数据行,提交时间一模一样。但业务需求是不能有多余的 log 出现,这明显是个问题。 问题是,重复请求导致的数据重复插入。这问题造成的后果很明显: 1.数据冗余,可能不单单多一条 2.有些业务需求不能有多余数据,造成服务问题 问题如图所示: 解决方式:如何将 同请求 A,不执行插入,而是读取前一个请求插入的数据并返回。解决后流程应该如下: 二、解决方案实战 1.单库单表解决方案 1.唯一索引 + 唯一字段 2.幂等 上面说的那种业务场景:sign_log 表会有 user_id、sign_id、sign_time 等。那么每次签到,每个人每天只有一条签到记录。 ...
- 下一篇
如何快速搭建一套在线教育平台?
现在在线教育平台越来越成为教育的主流,归根到底是因为线上教育的优势很大,打破地域与时间局限之外,可以轻易扩大招生规模,还可以在线直播与学生互动,让线上有更多的体验,把体验用户转化为自己的固定学生,吸引学生不仅在线上课堂,同时还可以到线下参与互动,直接感受课堂的气氛。此外拥有自己的在线教育平台,还可以塑造自己的品牌形象和知名度,对以后的帮助很有显著。那么,到底如何才能快速搭建出在线教育平台呢? 方案一:自建平台,从零开始(前期投资大,时间周期长)在线教育平台搭建首先需要从功能需求入手,分析、策划、设计、UI到代码功能实现都要提前策划好,正常来说需要招聘一个团队。 方案二:基于开源项目进行二次开发(前期投资小,时间周期稍长)基于开源项目,需要有较强的技术人员,对开源项目进行熟悉和二次开发。 方案三:购买一套成熟稳定的系统(前期投资一般,时间周期短)购买成熟的商业系统,一般情况下会有培训服务,可以最快搭建出在线教育平台。不符合自己的需求,一般也会有定制服务。 领课教育系统(一套开源免费的在线教育系统) 领课教育系统(roncoo-education)是基于领课网络多年的在线教育平台开发和运...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- SpringBoot2初体验,简单认识spring boot2并且搭建基础工程
- CentOS7,CentOS8安装Elasticsearch6.8.6
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- CentOS7,8上快速安装Gitea,搭建Git服务器
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- MySQL8.0.19开启GTID主从同步CentOS8
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- SpringBoot2全家桶,快速入门学习开发网站教程
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- CentOS8编译安装MySQL8.0.19