【问题标题】:How to pass data from gRPC interceptor to service method call?如何将数据从 gRPC 拦截器传递到服务方法调用?
【发布时间】:2017-12-09 07:05:03
【问题描述】:

我需要从我的ServerAuthIntereptor 传递一些数据来调用。

ServerAuthInterceptor:

// used in context parameters map
private static final String AUTH_CONTEXT = "authContext";
private static final Context.Key<Object> AUTH_CONTEXT_KEY = Context.key(AUTH_CONTEXT);

// ...

@Override
public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(
    ServerCall<ReqT, RespT> call, Metadata headers, ServerCallHandler<ReqT, RespT> next) {

    // check credentials from header

    // remember account and session token for usage later (eg. in logout)
    AuthContext authContext = new AuthContext();
    authContext.account = account;
    authContext.sessionToken = sessionToken;

    logger.info("Call {} allowed (account={}, authContext={})",
        new Object[] { call, account, authContext });

    Context context = Context
        .current()
        .withValue(AUTH_CONTEXT_KEY, authContext);

    return Contexts.interceptCall(context, call, headers, next);
}

// ...

/**
 * To be used from services
 * @return
 */
public static Account getCurrentContextAccount() {
    AuthContext authContext = (AuthContext) Context.current().key(AUTH_CONTEXT).get();
    return authContext.account;
}

在某些服务方法实现中,我尝试从当前上下文访问存储的“authContext”:

@Override
public void list(ListRequest request, StreamObserver<ListResponse> responseObserver) {
    logger.info("Starting list({}) ...", request);

     // ...

     account = ServerAuthInterceptor.getCurrentContextAccount();

但 authContext 是 null。 它有时会起作用,所以我相信它与线程(本地)有关。

什么是正确的方法?

【问题讨论】:

    标签: java rpc grpc


    【解决方案1】:

    上下文键使用引用相等。因此,您必须使用相同的密钥实例进行设置和获取。

    这段代码重新创建了密钥,所以它不会匹配:

    Context.current().key(AUTH_CONTEXT).get();
    

    它应该是:

    AUTH_CONTEXT_KEY.get();
    

    使用了引用相等,因此您可以将正常的 Java 可见性(公共、受保护、包私有、私有)规则应用于值,就像您可以使用 ThreadLocal 一样。

    【讨论】:

      【解决方案2】:

      由于某种原因,它不适用于 AuthContext 类,但如果我分别传递 2 个上下文值,它就会起作用:

      ServerAuthInterceptor:

      Context context = Context
              .current()
              .withValue(AUTH_TOKEN_KEY, sessionToken)
              .withValue(AUTH_ACCOUNT_KEY, account);
      

      服务调用:

      /**
       * To be used from services
       * @return
       */
      public static Account getCurrentContextAccount() {
          return (Account) AUTH_ACCOUNT_KEY.get();
      }
      
      /**
       * To be used from services
       * @return
       */
      public static String getCurrentContextSessionToken() {
          return (String) AUTH_TOKEN_KEY.get();
      }
      

      【讨论】:

        猜你喜欢
        • 2016-04-26
        • 2019-12-13
        • 2022-12-03
        • 2016-11-13
        • 2019-07-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多