我们有一个gPRC服务,需要在类的ThreadLocal变量中设置身份验证/身份信息,以便它正确调用另一个服务。 gPRC服务从请求中获取身份验证/身份信息,因此我正在考虑使用拦截器。
首先,我有一些代码如下。
public class ImpersonationInterceptor {
public <ReqT, RespT> interceptCall(
ServerCall<ReqT, RespT> serverCall, Metadata headers, ServerCallHandler<ReqT, RespT> next) {
Principal principal = ... // get the identify from the request
AuthContext.setPrincipal(principal); // underneath it uses a ThreadLocal.
return next.startCall(
new SimpleForwardingServerCall<>(call) {
public void close(Status status, Metadata trailers) {
AuthContext.setPrincipal(null); // clear the identity
}
}
)
}
}
问题。
非常感谢。
答案 0 :(得分:1)
对于此类上下文信息,您必须非常小心使用ThreadLocals,因为您不想意外地为客户端使用错误的身份。
gRPC的每个回调都可以在不同的线程上发生,而多个RPC的回调可以在同一个线程上发生。
您需要遵循Contexts.interceptCall()之类的模式。您必须在每次通话后设置/取消设置:
public class ImpersonationInterceptor {
public <ReqT, RespT> interceptCall(
ServerCall<ReqT, RespT> serverCall, Metadata headers, ServerCallHandler<ReqT, RespT> next) {
Principal principal = ...;
AuthContext.setPrincipal(principal);
try {
return new WrappingListener<>(next.startCall(call, headers), principal);
} finally {
AuthContext.clearPrincipal();
}
}
private static class WrappingListener<ReqT> extends
ForwardingServerCallListener.SimpleForwardingServerCallListener<ReqT> {
private final Principal principal;
public WrappingListener(ServerCall.Listener<ReqT> delegate, Principal principal) {
super(delegate);
this.principal = principal;
}
@Override
public void onMessage(ReqT message) {
AuthContext.setPrincipal(principal);
try {
super.onMessage(message);
} finally {
AuthContext.clearPrincipal();
}
}
... repeat for each method
}
}