当前位置: 首页 > 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.hskmm.com/?act=detail&tid=39123

相关文章:

  • 品牌故事不会写?这个AI指令可能帮你解决大问题
  • WebSocket
  • JWT令牌
  • 电梯调度编程结对项目总结
  • GuessGame两个版本的区别
  • 第二次作业--田佳吉
  • 电脑频繁卡顿?4个CMD命令揪出后台隐藏进程
  • 2025_软件工程师课程辅导
  • Graphiti:为智能体构建实时知识图谱,引领更聪明的 AI 时代
  • 《《《es相关
  • 人资新手必看,企业绩效的意义
  • 题解:P14309 【MX-S8-T2】配对
  • HuggingFace 库使用小技巧
  • 启动分布式mapreduce的过程以及prompt
  • 【ArcMap】复制选中的线并将其上移一段距离
  • 题解:AT_apc001_h Generalized Insertion Sort
  • 记一次thinkphp3.2项目迁移失败的原因。 is currently unable to handle this request. HTTP ERROR 500
  • 20232310 2025-2026-1 《网络与系统攻防技术》实验三实验报告
  • [SWPUCTF 2024 秋季新生赛]http标头 WP
  • 20251025 之所思 - 人生如梦
  • Jerrum–Sinclair 全有或全无定理
  • 一种解决所有 OI 问题的算法:Dream 算法
  • CobaltStrike流量分析
  • 【论文阅读】ASPS: Augmented Segment Anything Model for Polyp Segmentation - 指南
  • RuoYi-Cloud 认证实现
  • 初步学习计算机相关知识有感 - fang
  • 2025年自动上料机厂家权威推荐榜:螺旋上料机/真空上料机/粉末上料机,高效输送系统精准选型指南
  • 用代码将txt分别转换成列表和字典
  • 每日反思(2025_10_25)
  • AtCoder Beginner Contest 429 ABCDEF 题目解析