【发布时间】:2019-06-10 15:36:32
【问题描述】:
我正在将分布式系统代码库从 SOAP (JAX-WS) 迁移到 gRPC-java。 我们使用这个代码库来教授远程调用、容错、安全实现。
在 JAX-WS 架构上,有一个拦截器类(称为 SOAP 处理程序)可以拦截 SOAP 消息。您可以在客户端和服务器上配置处理程序。
作为参考,这是在 JAX-WS 上远程调用的完整序列:
- 客户端 - 创建端口(存根)并调用远程方法
- 存根 - 将 Java 对象转换为 SOAP 消息 (XML)
- ClientHandler - 拦截传出的 SOAP 消息并可以对其进行读/写
- 网络 - 发送的 SOAP 请求消息
- ServerHandler - 拦截传入的 SOAP 消息,可以读/写
- Tie - 将 SOAP 消息转换为 Java 对象
- 服务器 - 执行方法,响应
- ServerHandler - 拦截传出的 SOAP 响应,可以读/写
- 网络 - 已传输 SOAP 响应消息
- 客户端 - 创建端口(存根)并调用远程方法
- 存根 - 将 Java 对象转换为 SOAP 消息 (XML)
- ClientHandler - 拦截传入的 SOAP 消息
- 客户端 - 接收响应
通过这种方法,我们可以创建处理程序来记录 SOAP 消息并增加安全性,例如数字签名或加密。
我正在尝试在 Java (v1.17.2) 上使用 gRPC 提供类似的功能。
我的 gRPC 代码基于 this google tutorial,这是一个带有一元方法的简单 hello world。
基于these examples,我写了一个ClientInterceptor:
package example.grpc.client;
import java.util.Set;
import io.grpc.*;
public class HelloClientInterceptor implements ClientInterceptor {
@Override
public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(MethodDescriptor<ReqT, RespT> methodDescriptor,
CallOptions callOptions, Channel channel) {
return new ForwardingClientCall.SimpleForwardingClientCall<ReqT, RespT>(
channel.newCall(methodDescriptor, callOptions)) {
@Override
public void sendMessage(ReqT message) {
System.out.printf("Sending method '%s' message '%s'%n", methodDescriptor.getFullMethodName(),
message.toString());
super.sendMessage(message);
}
@Override
public void start(Listener<RespT> responseListener, Metadata headers) {
System.out.println(HelloClientInterceptor.class.getSimpleName());
ClientCall.Listener<RespT> listener = new ForwardingClientCallListener<RespT>() {
@Override
protected Listener<RespT> delegate() {
return responseListener;
}
@Override
public void onMessage(RespT message) {
System.out.printf("Received message '%s'%n", message.toString());
super.onMessage(message);
}
};
super.start(listener, headers);
}
};
}
}
我创建了一个ServerInterceptor:
package example.grpc.server;
import java.util.Set;
import io.grpc.*;
public class HelloServerInterceptor implements ServerInterceptor {
@Override
public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(ServerCall<ReqT, RespT> serverCall, Metadata metadata,
ServerCallHandler<ReqT, RespT> serverCallHandler) {
// print class name
System.out.println(HelloServerInterceptor.class.getSimpleName());
return Contexts.interceptCall(ctx, serverCall, metadata, serverCallHandler);
}
}
这是(最后)我的问题:
- 服务器拦截器如何查看方法执行前后的消息?
- 服务器拦截器如何修改消息?
- 客户端拦截器如何修改消息?
最终目标是能够编写一个 CipherClientHandler 和一个 CipherServerHandler 来加密线路上的消息字节。我知道 TLS 在实践中是正确的做法,但我希望学生进行自定义实现。
感谢您提供正确方向的任何指示!
【问题讨论】:
标签: java soap interceptor grpc grpc-java