【问题标题】:OAuth in gRPC using Java使用 Java 的 gRPC 中的 OAuth
【发布时间】:2018-05-04 23:37:36
【问题描述】:

我正在尝试使用拦截器在我的 gRPC 服务器和客户端应用程序之间实现 OAuth2,步骤如下:

  1. 客户端应用调用服务器的 gRPC 方法
  2. 服务器应用响应UNAUTHENTICATED 状态和标题中的redirect-url
  3. client获取redirect-url,用它访问Authorization server,最后得到access_token
  4. 客户端应用调用服务器的 gRPC 方法(这次使用access_token

但是,第 4 步似乎不可能仅在一次调用中完成,因为事务已经在第 2 步关闭。有没有办法在一次 gRPC 服务调用中完成这 4 个步骤?

这是我的 ClientInterceptor 类。我在代码中指出了 4 个步骤(参见代码 cmets)。

public class OAuthClientInterceptor implements ClientInterceptor {

    @Override
    public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(MethodDescriptor<ReqT, RespT> method, CallOptions callOptions, Channel next) {

        return new CheckedForwardingClientCall<ReqT, RespT>(next.newCall(method, callOptions)) {

            @Override
            public void checkedStart(Listener<RespT> responseListener, Metadata headers) {

                if (redirectUrl != null) {
                    try {
                        //[Step #3] Obtain the access token
                        accessToken = obtainAccessToken(redirectUrl);
                    } catch (ConnectException e) {
                        throw new StatusRuntimeException(Status.UNAUTHENTICATED.withCause(e));
                    }
                }
                if (accessToken != null) {
                    headers.put(Key.of("Authorization",
                        Metadata.ASCII_STRING_MARSHALLER), "Bearer " + accessToken);

                }
                if (recursiveCall) {
                    //[Step #4] PROBLEM: still results to UNAUTHENTICATED
                    next.newCall(method, callOptions).start(responseListener, headers);
                    recursiveCall = false;
                    return;
                }
                OAuthResponseListener<RespT> oAuthRespListener = new OAuthResponseListener(responseListener);
                oAuthRespListener.setUnauthenticatedListener(trailers->{

                    //[Step #2] Obtain the redirect-url
                    redirectUrl = trailers.get(Key.of("redirect-url", Metadata.ASCII_STRING_MARSHALLER));
                    recursiveCall = true;

                    //[Step #3 and 4] Invoke the retrieval of access token and the 2nd call to gRPC method
                    checkedStart(responseListener, headers);
                });
                //[Step #1] Call the gRPC method
                delegate().start(oAuthRespListener, headers);
            }
        };
    }
}

【问题讨论】:

标签: java oauth-2.0 spring-security-oauth2 grpc-java


【解决方案1】:

我已经解决了这个问题,但我希望找到一些内置的身份验证机制或多次调用 blockingStub 函数来支持这个 oAuth 流程,但找不到任何东西。

所以我至少拨打了两次blockingStub.invokeServerMethod()

  1. 知道它是否还没有被认证,并且能够获得redirect-url
  2. 能够调用 invokeServerMethod 并将 access_token 附加到标头。

请注意,我有 30 个服务器方法,我必须对所有这些方法调用执行相同的步骤。为了最大限度地减少每个服务器方法的代码重复,我创建了一个 RetryUtil 类,它将为每个服务器方法调用。这是我所做的:

public class GrpcClient {

    public SomeResponse callServerMethod() {
        //invoke the method twice
        return RetryUtil.retry(() -> blockingStub.invokeServerMethod(), 2); 
    }
}

public class RetryUtil {

    public static <T> T retry(Supplier<T> supplier, int retryCount) {

        StatusRuntimeException finalEx = null;
        for (int i=0; i<retryCount; i++) {
            try {
                return supplier.get();
            } catch (StatusRuntimeException e) {
                if (e.getStatus() != Status.UNAUTHENTICATED) {
                    throw e;
                }
                finalEx = e;
            }
        }
        throw finalEx;
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-30
    • 1970-01-01
    • 2011-02-02
    • 2017-09-25
    • 1970-01-01
    • 2020-09-08
    相关资源
    最近更新 更多