gRPC Java - 存储状态变量(用于用户身份验证)

时间:2018-06-18 08:15:03

标签: java spring-boot grpc grpc-java

我在SpringBoot(和SpringSecurity)环境中使用gRPC,并在连接时使用ServerInterceptor对用户进行身份验证。我将身份验证结果存储在Spring的SecurityContextHolder中。 (Followed this

private final AuthenticationManager manager;

@Autowired
public AuthenticatorInterceptor(final AuthenticationManager manager) {
    this.manager = manager;
}

@Override
public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(ServerCall<ReqT, RespT> serverCall,
                                                             Metadata metadata, ServerCallHandler<ReqT, RespT> serverCallHandler) {
    logger.info("Authorizing user information for GRPC access");

    final String authHeader = nullToEmpty(metadata.get(Metadata.Key.of("authorization", Metadata.ASCII_STRING_MARSHALLER)));
    if (!authHeader.startsWith("Basic ")) {
        logger.error("No Authentication Info found");
        throw Status.PERMISSION_DENIED.withDescription("No Authentication Info found").asRuntimeException();
    }

    try {
        final String[] tokens = decodeBasicAuth(authHeader);
        final String userName = tokens[0];

        if (authenticationIsRequired(userName)) {
            final Authentication pending = new UsernamePasswordAuthenticationToken(userName, tokens[1]);
            final Authentication result = manager.authenticate(pending);
            logger.info("Authentication success for this user");

            SecurityContextHolder.getContext().setAuthentication(result);
        }
    } catch (AuthenticationException e) {
        SecurityContextHolder.clearContext();
        logger.error("Authentication failed - No GRPC Access", e);
        throw Status.UNAUTHENTICATED.withDescription(e.getMessage()).withCause(e).asRuntimeException();
    }

    return serverCallHandler.startCall(serverCall, metadata);
}

但问题是身份验证在客户端泄露并共享。例如,如果客户端A连接并进行身份验证,然后当另一个客户端B连接时,客户端B已经使用客户端A的凭据进行了身份验证。

我想这是因为SecurityContext的默认SecurityContextHolder使用ThreadLocal来存储身份验证信息,而gRPC可能会重用不同连接的线程。

我应该在哪里存储身份验证信息?我看到了Context类(gRPC context),但无法理解(并且找不到任何资源)正确实现我所需的功能。

PS:我使用SpringBoot gRPC Starter来配置gRPC服务器及其拦截器。

0 个答案:

没有答案