如何将数据从 gRPC 拦截器传递到服务方法调用?
How to pass data from gRPC interceptor to service method call?
我需要从 ServerAuthIntereptor
传递一些数据来调用。
ServerAuthInterceptor:
// used in context parameters map
private static final String AUTH_CONTEXT = "authContext";
private static final Context.Key<Object> AUTH_CONTEXT_KEY = Context.key(AUTH_CONTEXT);
// ...
@Override
public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(
ServerCall<ReqT, RespT> call, Metadata headers, ServerCallHandler<ReqT, RespT> next) {
// check credentials from header
// remember account and session token for usage later (eg. in logout)
AuthContext authContext = new AuthContext();
authContext.account = account;
authContext.sessionToken = sessionToken;
logger.info("Call {} allowed (account={}, authContext={})",
new Object[] { call, account, authContext });
Context context = Context
.current()
.withValue(AUTH_CONTEXT_KEY, authContext);
return Contexts.interceptCall(context, call, headers, next);
}
// ...
/**
* To be used from services
* @return
*/
public static Account getCurrentContextAccount() {
AuthContext authContext = (AuthContext) Context.current().key(AUTH_CONTEXT).get();
return authContext.account;
}
在某些服务方法实现中,我尝试从当前上下文访问存储的 'authContext':
@Override
public void list(ListRequest request, StreamObserver<ListResponse> responseObserver) {
logger.info("Starting list({}) ...", request);
// ...
account = ServerAuthInterceptor.getCurrentContextAccount();
但是 authContext 是 null
。
它有时会起作用,所以我相信它与线程(本地)有关。
正确的做法是什么?
出于某种原因,它不适用于 AuthContext
class,但如果我分别传递 2 个上下文值,它会起作用:
服务器验证拦截器:
Context context = Context
.current()
.withValue(AUTH_TOKEN_KEY, sessionToken)
.withValue(AUTH_ACCOUNT_KEY, account);
服务电话:
/**
* To be used from services
* @return
*/
public static Account getCurrentContextAccount() {
return (Account) AUTH_ACCOUNT_KEY.get();
}
/**
* To be used from services
* @return
*/
public static String getCurrentContextSessionToken() {
return (String) AUTH_TOKEN_KEY.get();
}
上下文键使用引用相等性。因此,您必须使用相同的密钥实例来设置和获取。
此代码重新创建了密钥,因此它不匹配:
Context.current().key(AUTH_CONTEXT).get();
应该是:
AUTH_CONTEXT_KEY.get();
使用引用相等性,因此您可以对值应用正常的 Java 可见性(public、受保护、包私有、私有)规则,就像您可以对 ThreadLocal
所做的那样.
我需要从 ServerAuthIntereptor
传递一些数据来调用。
ServerAuthInterceptor:
// used in context parameters map
private static final String AUTH_CONTEXT = "authContext";
private static final Context.Key<Object> AUTH_CONTEXT_KEY = Context.key(AUTH_CONTEXT);
// ...
@Override
public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(
ServerCall<ReqT, RespT> call, Metadata headers, ServerCallHandler<ReqT, RespT> next) {
// check credentials from header
// remember account and session token for usage later (eg. in logout)
AuthContext authContext = new AuthContext();
authContext.account = account;
authContext.sessionToken = sessionToken;
logger.info("Call {} allowed (account={}, authContext={})",
new Object[] { call, account, authContext });
Context context = Context
.current()
.withValue(AUTH_CONTEXT_KEY, authContext);
return Contexts.interceptCall(context, call, headers, next);
}
// ...
/**
* To be used from services
* @return
*/
public static Account getCurrentContextAccount() {
AuthContext authContext = (AuthContext) Context.current().key(AUTH_CONTEXT).get();
return authContext.account;
}
在某些服务方法实现中,我尝试从当前上下文访问存储的 'authContext':
@Override
public void list(ListRequest request, StreamObserver<ListResponse> responseObserver) {
logger.info("Starting list({}) ...", request);
// ...
account = ServerAuthInterceptor.getCurrentContextAccount();
但是 authContext 是 null
。
它有时会起作用,所以我相信它与线程(本地)有关。
正确的做法是什么?
出于某种原因,它不适用于 AuthContext
class,但如果我分别传递 2 个上下文值,它会起作用:
服务器验证拦截器:
Context context = Context
.current()
.withValue(AUTH_TOKEN_KEY, sessionToken)
.withValue(AUTH_ACCOUNT_KEY, account);
服务电话:
/**
* To be used from services
* @return
*/
public static Account getCurrentContextAccount() {
return (Account) AUTH_ACCOUNT_KEY.get();
}
/**
* To be used from services
* @return
*/
public static String getCurrentContextSessionToken() {
return (String) AUTH_TOKEN_KEY.get();
}
上下文键使用引用相等性。因此,您必须使用相同的密钥实例来设置和获取。
此代码重新创建了密钥,因此它不匹配:
Context.current().key(AUTH_CONTEXT).get();
应该是:
AUTH_CONTEXT_KEY.get();
使用引用相等性,因此您可以对值应用正常的 Java 可见性(public、受保护、包私有、私有)规则,就像您可以对 ThreadLocal
所做的那样.