欢迎光临
我们一直在努力

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


背景分析

本文主要来探讨第三部 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 客户端的配置

总结

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

赞(0)
未经允许不得转载:ITyet » Spring Cloud OAuth 实现微服务内部Token传递的源码解析
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址