最近开始接触到grpc并用它写了一些接口,使用了Spring Security来做用户身份校验,但当我写的正起劲的时候发现了一个问题
生成的service里面的方法只有request和response,这就让我很头疼了,总不可能在request里面再放一个token吧
@GrpcService
class TestService:TestrdServiceGrpc.TestServiceImplBase() {
override fun method(
request: methodRequest,
responseObserver: StreamObserver<methodResponse>
) {
super.method(request, responseObserver)
}
}
最开始想到的是通过SecurityContextHolder.getContext().authentication
来获取,但是获取到的变量一直都是null
,经过一番折腾,发现在运行到DefaultAuthenticatingServerInterceptor
的一段代码的时候就清空了
......
finally {
SecurityContextHolder.clearContext();
......
log.debug("startCall - Authentication cleared");
}
而执行clearContext();
的此刻还远远没到执行我所写的代码
就在我满脑子问号的时候,向上翻阅源代码的时候偶然间发现了这行代码,在这里把Authentication
给👴塞到了Context
里边
final Context context = Context.current().withValue(AUTHENTICATION_CONTEXT_KEY, authentication);
好家伙,原来是给存到了Context
里面。经过我反复查看Context
的源代码,找到了获取该变量的方法
/**
* Get the value from the {@link #current()} context for this key.
*/
@SuppressWarnings("unchecked")
public T get() {
return get(Context.current());
}
@GrpcService
class TestService : TestServiceGrpc.TestServiceImplBase() {
override fun method(
request: Request,
responseObserver: StreamObserver<Response>
) {
val authentication = AUTHENTICATION_CONTEXT_KEY.get()
val response = Response {
message = "hello ${authentication.principal}"
}
responseObserver.onNext(response)
responseObserver.onCompleted()
}
}
当然,你也可以自己向Context
里面放变量,更多用法可参考Github上别人的例子
//存放
Context.current().withValue(KEY, VALUE)
//读取
KEY.get()
Comments | NOTHING