You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring服务向gRPC拦截器传递Bearer Token及信息失败排查

问题分析与解决方案

核心问题:Context未正确绑定到调用作用域

你当前代码的问题在于Context.current().withValue()方法会返回一个新的Context实例,但你并没有将这个新Context设置为当前上下文,也没有在这个新Context的作用域内执行gRPC调用。原来的代码只是创建了新Context,但实际执行grpcClient.getEmployee(...)时,仍然使用的是原来的Context,所以拦截器中获取不到值。

正确的实现方式

方式1:使用Context.run()包裹gRPC调用(推荐)

Context.run()会将新Context设置为当前上下文,并在执行完传入的任务后自动恢复原来的Context,无需手动管理:

// spring-service方法修改
public Employee getEmployee() {
  ...
  // 创建包含用户信息的新Context
  Context newContext = Context.current()
      .withValue(ContextKeyHolder.USER_INFO, currentUser.getUsername())
      .withValue(ContextKeyHolder.BEARER, currentUser.getBearerToken());
  
  // 在新Context的作用域内执行gRPC调用
  return newContext.run(() -> grpcClient.getEmployee(...));
}

方式2:手动attach/detach Context

如果需要更细粒度的控制,可以手动绑定和恢复Context:

// spring-service方法修改
public Employee getEmployee() {
  ...
  Context oldContext = Context.current();
  Context newContext = oldContext
      .withValue(ContextKeyHolder.USER_INFO, currentUser.getUsername())
      .withValue(ContextKeyHolder.BEARER, currentUser.getBearerToken());
  
  // 将新Context设置为当前上下文
  Context attachedContext = newContext.attach();
  try {
    return grpcClient.getEmployee(...);
  } finally {
    // 恢复原来的Context
    attachedContext.detach(oldContext);
  }
}

关于ThreadLocal的选择

不推荐使用ThreadLocal,原因如下:

  • Spring GraphQL的DataFetcher可能会在异步线程池中执行,线程会发生切换,ThreadLocal存储的值无法跨线程传递,导致拦截器中获取不到数据。
  • gRPC的Context本身就是为了解决跨线程、异步场景下的上下文传递设计的,它会自动跟随调用栈(包括异步回调)传递,比ThreadLocal更适配gRPC和Spring GraphQL的异步执行模型。

拦截器补充优化

确保在拦截器中正确获取值并设置到gRPC请求头:

@Override
public void start(Listener<RespT> responseListener, Metadata headers) {
  String userInfo = ContextKeyHolder.USER_INFO.get(Context.current());
  String bearerToken = ContextKeyHolder.BEARER.get(Context.current());
  
  if (userInfo != null) {
    headers.put(Metadata.Key.of("user-info", Metadata.ASCII_STRING_MARSHALLER), userInfo);
  }
  if (bearerToken != null) {
    headers.put(Metadata.Key.of("Authorization", Metadata.ASCII_STRING_MARSHALLER), "Bearer " + bearerToken);
  }
  
  super.start(responseListener, headers);
}

内容的提问来源于stack exchange,提问作者Govinda Sakhare

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 04:10:36