【问题标题】:Access message request in first gRPC interceptor before headers in second gRPC interceptor在第二个 gRPC 拦截器中的标头之前访问第一个 gRPC 拦截器中的消息请求
【发布时间】:2021-09-10 19:33:34
【问题描述】:

我的问题类似于this 的帖子,但它似乎很旧且不活跃,所以我在这里重新发布。

基本上,我有一个奇怪的用例,我需要在 gRPC 请求正文(而不是标头)中发送我的授权令牌。我的想法是使用一组拦截器,其中第一个将读取 gRPC 消息并根据消息中的令牌设置 Authorization 标头。第二个拦截器将是使用的普通授权拦截器,它将读取刚刚设置为 Authorization 标头的令牌。我希望这样做,因为这样可以让我重用已经存在的授权拦截器代码。

我这样称呼拦截器:

ServerInterceptors.intercept(
    new MyResource(resource),
    new SecondInterceptorHeaderAuthorization(),
    new FirstInterceptorReadTokenFromMessageBody()
)

FirstInterceptorReadTokenFromMessageBody() 看起来像这样:

public class FirstInterceptorReadTokenFromMessageBody implements ServerInterceptor {

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


    return new ForwardingServerCallListener.SimpleForwardingServerCallListener<ReqT>(
            next.startCall(call, headers)) {
          @Override
          public void onMessage(ReqT request) {

            var value = ((MyRequest) request).getAuthorization();
            Metadata.Key<String> key =
                Metadata.Key.of("Authorization", Metadata.ASCII_STRING_MARSHALLER);
            headers.put(key, value);

            super.onMessage(request);
          }
        };
  }
}

还有SecondInterceptorHeaderAuthorization()拦截器:

public class SecondInterceptorHeaderAuthorization implements ServerInterceptor {

  public <ReqT, RespT> Listener<ReqT> interceptCall(
      ServerCall<ReqT, RespT> call, Metadata headers, ServerCallHandler<ReqT, RespT> next) {
      .... handle authorization here
}

拦截器以相反的顺序正确触发;请求最终由SecondInterceptorHeaderAuthorization() 处理,首先是标题授权,然后是FirstInterceptorReadTokenFromMessageBody()。我怎样才能让消息拦截器先运行,然后是标头拦截器?这甚至可能吗?有没有更好的方法来解决我错过的这个问题?

【问题讨论】:

  • 我认为你应该把 header 放在客户端的 Metadata 中,就像 traceId rathar 一样,而不是放在 message 中,所以你只需要一个拦截器来处理授权,并且可以直接从 header 中读取。
  • 很乐意这样做,除了请求通过的代理正在剥离所有标头。我想我已经找到了解决方案。等我有几分钟的时间再写。

标签: java grpc grpc-java


【解决方案1】:

我想通了。基本上,我遵循了线程here中描述的内容

我的FirstInterceptorReadTokenFromMessageBody 班级现在看起来像这样:

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

    final Listener<ReqT> authorizationLookUpCallListener =
        new ForwardingServerCallListener<ReqT>() {
          private final Listener<ReqT> NOOP = new Listener<ReqT>() {};
          private Listener<ReqT> delegate = NOOP;

          @Override
          protected Listener<ReqT> delegate() {
            return delegate;
          }

          @Override
          public void onMessage(ReqT message) {
            // ensures that this interceptor only run first
            if (delegate == NOOP) {
              if (message instanceof MyRequest) {
                String auth_token = ((MyRequest) message).getAuthToken();
                headers.put(
                    Metadata.Key.of("my-auth-token-header", Metadata.ASCII_STRING_MARSHALLER),
                    auth_token);
              }
              delegate = next.startCall(call, headers);
            }
            super.onMessage(message);
          }
        };

    ServerCallHandler<ReqT, RespT> handler =
        (call1, headers1) -> {
          call1.request(1);
          return authorizationLookUpCallListener;
        };

    return handler.startCall(call, headers);
  }
}

【讨论】:

    猜你喜欢
    • 2018-05-31
    • 1970-01-01
    • 2021-05-11
    • 2019-07-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-22
    相关资源
    最近更新 更多