I need to pass some data from my ServerAuthIntereptor
to call.
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;
}
In some service method implementation i try to access that stored 'authContext' from current context:
@Override
public void list(ListRequest request, StreamObserver<ListResponse> responseObserver) {
logger.info("Starting list({}) ...", request);
// ...
account = ServerAuthInterceptor.getCurrentContextAccount();
But authContext is null
.
It's working sometimes so i believe it's related to threads(locals).
What is proper way to do it?
Context Keys use reference equality. Thus, you must use the same key instance for setting and getting.
This code re-created the key, so it wouldn't match:
Context.current().key(AUTH_CONTEXT).get();
Instead it should have been:
AUTH_CONTEXT_KEY.get();
Reference equality is used so you can apply normal Java visibility (public, protected, package-private, private) rules to the value, as you can do with ThreadLocal
.
For some reason it does not work fot AuthContext
class, but it works if i pass 2 context values separately:
ServerAuthInterceptor:
Context context = Context
.current()
.withValue(AUTH_TOKEN_KEY, sessionToken)
.withValue(AUTH_ACCOUNT_KEY, account);
Service call:
/**
* 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();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With