Spring Cloud OAuth 实现微服务内部Token传递的源码解析

背景分析

本文主要来探讨第三部 A --> B ,token 自定维护的源码实现

如何实现token 传递

配置OAuth2FeignRequestInterceptor 即可

  • 此类是Feign 的拦截器实现

1@Bean 2@ConditionalOnProperty("security.oauth2.client.client-id") 3public RequestInterceptor oauth2FeignRequestInterceptor(OAuth2ClientContext oAuth2ClientContext, 4 OAuth2ProtectedResourceDetails resource,) { 5 return new OAuth2FeignRequestInterceptor(oAuth2ClientContext, resource); 6}

源码解析

  • 获取上下文中的token ,组装到请求头

    public class OAuth2FeignRequestInterceptor implements RequestInterceptor { // 给请求增加 token @Override public void apply(RequestTemplate template) { template.header(header, extract(tokenType)); }

    1protected String extract(String tokenType) { 2 OAuth2AccessToken accessToken = getToken(); 3 return String.format("%s %s", tokenType, accessToken.getValue()); 4} 5 6// 从spring security 上下文中获取token 7public OAuth2AccessToken getToken() { 8 9 OAuth2AccessToken accessToken = oAuth2ClientContext.getAccessToken(); 10 if (accessToken == null || accessToken.isExpired()) { 11 try { 12 accessToken = acquireAccessToken(); 13 } 14 } 15 return accessToken; 16}

    }

  • 再来看AccessTokenContextRelay, 上下文token 中转器.非常简单从上下文获取认证信息得到把 token 放到上下文

    public class AccessTokenContextRelay {

    1private OAuth2ClientContext context; 2 3public AccessTokenContextRelay(OAuth2ClientContext context) { 4 this.context = context; 5} 6 7public boolean copyToken() { 8 if (context.getAccessToken() == null) { 9 Authentication authentication = SecurityContextHolder.getContext() 10 .getAuthentication(); 11 if (authentication != null) { 12 Object details = authentication.getDetails(); 13 if (details instanceof OAuth2AuthenticationDetails) { 14 OAuth2AuthenticationDetails holder = (OAuth2AuthenticationDetails) details; 15 String token = holder.getTokenValue(); 16 DefaultOAuth2AccessToken accessToken = new DefaultOAuth2AccessToken( 17 token); 18 String tokenType = holder.getTokenType(); 19 if (tokenType != null) { 20 accessToken.setTokenType(tokenType); 21 } 22 context.setAccessToken(accessToken); 23 return true; 24 } 25 } 26 } 27 return false; 28}

    }

  • 什么时候执行中转,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; }

    1accessTokenContextRelay.copyToken(); 2if (oAuth2ClientContext != null 3 && oAuth2ClientContext.getAccessToken() != null) { 4 super.apply(template); 5}

    }

  • 手动调用accessTokenContextRelay的copy,当然需要覆盖原生oauth 客户端的配置

总结

欢迎关注我们获得更多的好玩JavaEE 实践

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )

Spring Cloud OAuth 实现微服务内部Token传递的源码解析 - HelloWorld