当前位置: 首页 > news >正文

用户上下文透传机制详解

RuoYi-Cloud 用户上下文透传机制详解

引言

在微服务架构中,用户上下文的传递是一个关键问题。当一个请求在多个微服务之间调用时,如何确保用户身份信息能够正确传递到每个服务中,是实现安全认证和权限控制的基础。RuoYi-Cloud 通过 TransmittableThreadLocal 和 Feign 拦截器的组合,实现了高效的用户上下文透传。

1. 核心组件介绍

1.1 TransmittableThreadLocal

RuoYi-Cloud 使用阿里巴巴开源的 TransmittableThreadLocal 来存储用户上下文信息。相比于标准的 ThreadLocal,TransmittableThreadLocal 能够在父子线程之间传递数据,解决了异步场景下的上下文传递问题。

SecurityContextHolder 中,定义了基于 TransmittableThreadLocal 的线程上下文:

private static final TransmittableThreadLocal<Map<String, Object>> THREAD_LOCAL = new TransmittableThreadLocal<>();

1.2 Feign 拦截器

Feign 是 Spring Cloud 中常用的声明式 HTTP 客户端,用于服务间的调用。为了在 Feign 调用中传递用户上下文,RuoYi-Cloud 实现了自定义的 FeignRequestInterceptor

2. 用户上下文透传实现机制

2.1 上下文存储

用户上下文信息存储在 SecurityContextHolder 中,主要包括:

  1. 用户ID:user_id
  2. 用户名:username
  3. 用户标识:user_key
  4. 登录用户对象:login_user
  5. 角色权限:role_permission

这些信息通过 TransmittableThreadLocal存储,确保在线程间正确传递。

2.2 网关到业务服务的上下文传递

当请求从网关转发到业务服务时,网关已经在请求头中添加了用户信息:

// 设置用户信息到请求
addHeader(mutate, SecurityConstants.USER_KEY, userkey);
addHeader(mutate, SecurityConstants.DETAILS_USER_ID, userid);
addHeader(mutate, SecurityConstants.DETAILS_USERNAME, username);

业务服务通过 HeaderInterceptor 拦截器从请求头中提取用户信息并存储到 SecurityContextHolder 中:

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {if (!(handler instanceof HandlerMethod)) {return true;}SecurityContextHolder.setUserId(ServletUtils.getHeader(request, SecurityConstants.DETAILS_USER_ID));SecurityContextHolder.setUserName(ServletUtils.getHeader(request, SecurityConstants.DETAILS_USERNAME));SecurityContextHolder.setUserKey(ServletUtils.getHeader(request, SecurityConstants.USER_KEY));// ...return true;
}

2.3 Feign 调用中的上下文传递

当业务服务需要通过 Feign 调用其他服务时,FeignRequestInterceptor会自动将当前线程中的用户上下文信息添加到 Feign 请求的头部:

@Override
public void apply(RequestTemplate requestTemplate) {HttpServletRequest httpServletRequest = ServletUtils.getRequest();if (StringUtils.isNotNull(httpServletRequest)) {Map<String, String> headers = ServletUtils.getHeaders(httpServletRequest);// 传递用户信息请求头,防止丢失String userId = headers.get(SecurityConstants.DETAILS_USER_ID);if (StringUtils.isNotEmpty(userId)) {requestTemplate.header(SecurityConstants.DETAILS_USER_ID, userId);}String userKey = headers.get(SecurityConstants.USER_KEY);if (StringUtils.isNotEmpty(userKey)) {requestTemplate.header(SecurityConstants.USER_KEY, userKey);}String userName = headers.get(SecurityConstants.DETAILS_USERNAME);if (StringUtils.isNotEmpty(userName)) {requestTemplate.header(SecurityConstants.DETAILS_USERNAME, userName);}String authentication = headers.get(SecurityConstants.AUTHORIZATION_HEADER);if (StringUtils.isNotEmpty(authentication)) {requestTemplate.header(SecurityConstants.AUTHORIZATION_HEADER, authentication);}// 配置客户端IPrequestTemplate.header("X-Forwarded-For", IpUtils.getIpAddr());}
}

2.4 被调用服务的上下文处理

被调用的服务同样配置了 HeaderInterceptor拦截器,会从请求头中提取用户信息并存储到 SecurityContextHolder 中,从而完成整个调用链路上下文的传递。

3. 完整流程示例

以下是一个完整的用户上下文透传流程:

  1. 用户发起业务请求到网关
  2. 网关进行 JWT 验证,提取用户信息并添加到请求头
  3. 网关将请求转发到业务服务 A
  4. 业务服务 A 的 HeaderInterceptor 从请求头提取用户信息,存储到 SecurityContextHolder
  5. 业务服务 A 通过 Feign 调用业务服务 B
  6. FeignRequestInterceptorSecurityContextHolder中的用户信息添加到 Feign 请求头
  7. 业务服务 B 的 HeaderInterceptor从请求头提取用户信息,存储到 SecurityContextHolder
  8. 业务服务 B 处理请求,通过 SecurityContextHolder 获取用户信息
  9. 业务服务 B 返回结果给业务服务 A
  10. 业务服务 A 返回结果给网关
  11. 网关返回结果给用户

4. 技术优势

4.1 透明性

整个上下文传递过程对业务代码是透明的,开发者无需手动处理用户信息的传递。

4.2 异步支持

通过 TransmittableThreadLocal,即使在异步环境下也能正确传递用户上下文。

4.3 安全性

用户信息通过请求头传递,避免了在 URL 或请求体中暴露敏感信息。

4.4 可扩展性

通过配置不同的拦截器和过滤器,可以轻松扩展上下文传递的内容。

5. 配置要点

5.1 Feign 配置

FeignAutoConfiguration中注册了 Feign 拦截器:

@Configuration
public class FeignAutoConfiguration {@Beanpublic RequestInterceptor requestInterceptor() {return new FeignRequestInterceptor();}
}

5.2 拦截器配置

WebMvcConfig中配置了 HeaderInterceptor

@Override
public void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(getHeaderInterceptor()).addPathPatterns("/**").excludePathPatterns(excludeUrls).order(-10);
}

结论

RuoYi-Cloud 通过 TransmittableThreadLocal 和 Feign 拦截器的组合,实现了高效、安全、透明的用户上下文透传机制。这种设计不仅解决了微服务架构中用户身份传递的问题,还保证了在异步环境下上下文的正确传递,为构建安全可靠的微服务系统提供了坚实的基础。

http://www.zskr.cn/news/30558.html

相关文章:

  • GuessGame两个版本的区别
  • 2025_软件工程师课程辅导
  • 《《《es相关
  • 人资新手必看,企业绩效的意义
  • 题解:P14309 【MX-S8-T2】配对
  • 【ArcMap】复制选中的线并将其上移一段距离
  • HuggingFace 库使用小技巧
  • 【打造自己的 DeepSeek】第 2 期:怎么安装自己的 DeepSeek?
  • 一种解决所有 OI 问题的算法:Dream 算法
  • CobaltStrike流量分析
  • 2025年自动上料机厂家权威推荐榜:螺旋上料机/真空上料机/粉末上料机,高效输送系统精准选型指南
  • 建立VLAN间通信
  • 详细介绍:React Native 中的 useState、Context
  • 明天的任务
  • 深度神经网络 —— 使用深度自动编码器进行手写数字的去噪音
  • 完整教程:Webpack5 第四节
  • 完整教程:ACWing08:高精度专题
  • 使用本地git命令行拉取github.com软件仓库public项目
  • 10.25 CSP-S模拟39/2025多校冲刺CSP模拟赛8 改题记录
  • 嵌入子流形
  • 玩转单片机之智能车小露——数字与字符串的转换与打印
  • linux磁盘管理-RAID介绍 - 详解
  • Link-Cut Tree
  • 线段上随机取n个点的最大距离期望
  • 第5天(中等题 滑动窗口、逆向思维)
  • Meet in the middle 学习笔记
  • 虚拟机下 安装 ubuntu 18.04
  • 路径规划算法学习Day2:广度优先搜索算法(BFS)
  • 完整教程:ros_control 中 hardware_interface 教程
  • 飞牛NAS的SSL证书过期,又开启了强制HTTPS,进不去界面修改SSL怎么办? - 详解