java 如何将不记名令牌和其他信息从Spring服务传递到Grpc拦截器?

5jvtdoz2  于 2023-02-02  发布在  Java
关注(0)|答案(1)|浏览(133)

我有一个Spring GraphQL应用程序,它使用gRPC协议调用其他内部微服务。我需要将承载令牌和其他信息设置到gRPC头,我相信我们可以使用gRPC拦截器(ClientInterceptor实现)设置它。
我尝试了以下方法:
基于How to Access attributes from grpc Context.current()?,我创建了一个键,这样我们就可以在spring-service和interceptor中引用它

public class ContextKeyHolder {
  public static Context.Key<String> USER_INFO = Context.key("USER");
  public static Context.Key<String> BEARER = Context.key("BEARER");
}

// spring-service method
public Employee getEmployee() {
  ...
  Context.current().withValue(ContextKeyHolder.USER_INFO, currentUser.getUsername());
  Context.current().withValue(ContextKeyHolder.BEARER, currentUser.getBearerToken());
  return grpcClient.getEmployee(...);
}

// interceptCall implementation
public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(MethodDescriptor<ReqT, RespT> methodDescriptor,
    CallOptions callOptions, Channel channel) {
    return new ForwardingClientCall.SimpleForwardingClientCall<>(
      channel.newCall(methodDescriptor, callOptions)) {
     
      @Override
      public void start(Listener<RespT> responseListener, Metadata headers) {
        ...
        
        String userInfo = ContextKeyHolder.USER_INFO.get(Context.current());
        System.out.println("user => " + userInfo);
        
        ...
        super.start(responseListener, headers);
      }
    };
  }

这里我在拦截器方法中获得了null userInfo。我在这里错过了什么吗?
另一种选择是使用ThreadLocal来保存上下文,但我不确定这是否是正确的选择。

h6my8fg2

h6my8fg21#

在调用时需要使用您创建的上下文。因此,您的代码应该是:

return Context.current()
   .withValue(ContextKeyHolder.USER_INFO, currentUser.getUsername())
   .withValue(ContextKeyHolder.BEARER, currentUser.getBearerToken())
   .call(() -> { return grpcClient.getEmployee(...);});

或者:

Context oldContext = 
   Context.current()
     .withValue(ContextKeyHolder.USER_INFO, currentUser.getUsername())
     .withValue(ContextKeyHolder.BEARER, currentUser.getBearerToken())
     .attach();
  
  Employee valueToReturn = grpcClient.getEmployee(...);
  Context.current().detach(oldContext);
  return valueToReturn;

相关问题