博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Spring Cloud OAuth 微服务内部Token传递的源码实现解析
阅读量:5811 次
发布时间:2019-06-18

本文共 2878 字,大约阅读时间需要 9 分钟。

背景分析

  • 1.客户端携带认证中心发放的token,请求资源服务器A

  • 2.客户端携带令牌直接访问资源服务器,资源服务器通过对token 的校验 判断用户的合法性,并保存到上下文中

  • 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
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://juejin.im/post/5cbfd65ce51d456e781f2025

你可能感兴趣的文章
Spring Web Services 3.0.4.RELEASE和2.4.3.RELEASE发布
查看>>
有关GitHub仓库分支的几个问题
查看>>
无服务器计算的黑暗面:程序移植没那么容易
查看>>
云原生的浪潮下,为什么运维人员适合学习Go语言?
查看>>
Webpack入门教程三十
查看>>
EAServer 6.1 .NET Client Support
查看>>
锐捷交换机密码恢复(1)
查看>>
Kali linux virtualbox rc=1908 错误解决办法
查看>>
linux软件包管理之三(源代码安装)
查看>>
数据库三范式是什么?
查看>>
[转载]设置Ubuntu自动连接无线,无须再输入密钥环和无线密码
查看>>
九叔Xen App测试报告
查看>>
Apache配置
查看>>
Ext gridPanel 单元格数据的渲染
查看>>
Android SDK 的下载代理
查看>>
Method Swizzling对Method的要求
查看>>
佛祖保佑,永不宕机
查看>>
四、配置开机自动启动Nginx + PHP【LNMP安装 】
查看>>
LNMP一键安装
查看>>
SQL Server数据库概述
查看>>