如何访问我定义的java grpc服务的请求元数据?

对于某些背景,我试图使用grpc auth来为我定义的某些服务提供安全性。

让我们看看我是否可以问这是一种有意义的方式。 对于我的python代码,实现服务器端代码非常容易。

class TestServiceServer(service_pb2.TestServiceServer): def TestHello(self, request, context): ## credential metadata for the incoming request metadata = context.invocation_metadata() ## authenticate the user using the metadata 

所以,正如你所知,我能够很容易地从“上下文”中获取元数据。 对我来说更难的是在java中做同样的事情。

 public class TestImpl extends TestServiceGrpc.TestServiceImplBase { @Override public void testHello(TestRequest req, StreamObserver responseObserver) { // How do I get access to similar request metadata here? // from the parameter positions, it looks like it should be // "responseObserver" but that doesn't seem similar to "context" } } 

我承认我的问题来自几个方向。

1)我不熟悉Java

2)我大量使用python的“pdb”来调试类,看看我可以使用哪些方法。 我不知道/我不熟悉java的类似工具。

3)此时文档似乎相当稀疏​​。 它向您展示了如何在服务器端设置ssl连接,但是我找不到服务器的示例来查看请求元数据,正如我在python中所示。

有人可以给我一个如何做到这一点的想法,或者可能在python的pdb中向我展示一个有用的java调试工具吗?

编辑/答案:

我需要先写一个实现接口ServerInterceptor的定义。

 private class TestInterceptor implements ServerInterceptor { .... 

然后,在实际绑定我的服务和构建我的服务器之前,我需要这样做。

 TestImpl service = new TestImpl(); ServerServiceDefinition intercepted = ServerInterceptors.intercept(service, new TestInterceptor()); 

现在我能够创建服务器了。

 server = NettyServerBuilder.forPort(port) // enable tls .useTransportSecurity( new File(serverCert), new File(serverKey) ) .addService( intercepted // had been "new TestImpl()" ) .build(); server.start(); 

当我触发客户端请求时,这允许实际调用我的ServerInterceptor。

这个链接非常有助于解决这个问题。

使用ServerInterceptor ,然后通过Context传播身份。 这允许您具有用于身份validation的中央策略。

拦截器可以从Metadata headers检索标识。 然后应validation身份。 然后可以通过io.grpc.Context将经过validation的身份传达给应用程序(即testHello ):

 /** Interceptor that validates user's identity. */ class MyAuthInterceptor implements ServerInterceptor { public static final Context.Key USER_IDENTITY = Context.key("identity"); // "identity" is just for debugging @Override public  ServerCall.Listener interceptCall( ServerCall call, Metadata headers, ServerCallHandler next) { // You need to implement validateIdentity Object identity = validateIdentity(headers); if (identity == null) { // this is optional, depending on your needs // Assume user not authenticated call.close(Status.UNAUTENTICATED.withDescription("some more info"), new Metadata()); return new ServerCall.Listener() {}; } Context context = Context.current().withValue(USER_IDENTITY, identity); return Contexts.interceptCall(context, call, headers, next); } } public class TestImpl extends TestServiceGrpc.TestServiceImplBase { @Override public void testHello(TestRequest req, StreamObserver responseObserver) { // Access to identity. Object identity = MyAuthInterceptor.USER_IDENTITY.get(); ... } } // Need to use ServerInterceptors to enable the interceptor Server server = ServerBuilder.forPort(PORT) .addService(ServerInterceptors.intercept(new TestImpl(), new MyAuthInterceptor())) .build() .start();