首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Grpc Java SSL相互认证

Grpc Java SSL相互认证
EN

Stack Overflow用户
提问于 2015-08-26 09:07:40
回答 2查看 4.8K关注 0票数 3

我想知道在GrpcSslContext中需要设置什么才能使Grpc客户端使用服务器进行SSL身份验证?

目前,以下代码用于从服务器到客户端的常规单向SSL身份验证。

在服务器上,

代码语言:javascript
复制
SslContext sslContext = GrpcSslContexts.forServer(new File(pathToOwnCertPemFile), new File(pathToOwnPrivateKeyPemFile)).trustManager(new File(pathToClientCertPemFile)).build();

ServerImpl server = NettyServerBuilder
        .forPort(port)
        .sslContext(sslContext)
        .addService(MyGrpc.bindService(new MyGrpcService()))
        .build().start();

在客户那里,

代码语言:javascript
复制
SslContext sslContext = GrpcSslContexts.forClient().trustManager(new File(pathToServerCertPemFile)).keyManager(new File(pathToOwnCertPemFile), new File(pathToOwnPrivateKeyPemFile)).build();

ChannelImpl channel = NettyChannelBuilder.forAddress(host, port)
                .negotiationType(NegotiationType.TLS)
                .sslContext(sslContext).build();

blockingStub = MyGrpc.newBlockingStub(channel);
asyncStub = MyGrpc.newStub(channel);

据gRPC at https://github.com/grpc/grpc-java/blob/master/SECURITY.md说,

如果需要相互身份验证,也可以通过创建适当的SslContext来支持这一点。

我想知道我是否正确地初始化了GrpcSslContexts?

如有任何意见或意见,敬请见谅。

更新

在进一步排除故障时,我注意到CertificateRequest消息(如握手中所述)从未发送到客户端以启动客户端身份验证。

我的服务器日志的摘录如下:.

代码语言:javascript
复制
*** ECDH ServerKeyExchange
Signature Algorithm SHA512withRSA
Server key: Sun EC public key, 256 bits
public x coord: 81392923578261760187813715443713168545877454618233337093852615933913992434989
public y coord: 26389586381130695169212775668808794166799180199461581135201001980310825571555
parameters: secp256r1 NIST P-256, X9.62 prime256v1
*** ServerHelloDone
[write] MD5 and SHA1 hashes: len = 1617
0000: 02 00 00 56 03 03 55 DF 34 10 9C 73 B5 00 C2 70 ...V..U.4..s...p
0010: FD B8 CC 36 5B 83 87 70 5B 74 A3 D2 AD B7 75 3B ...6[..p[t....u;
....

我开始怀疑这可能是gRPC中固有的错误。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-08-31 17:50:10

编辑:支持被添加。创建自己的SslContext并将其传递给NettyChannelBuilder.sslContext(),确保通过SslContextBuilder.clientAuth()请求客户端证书。然后,对于每个RPC,检查ClientCall.getAttributes()并通过Grpc.TRANSPORT_ATTR_SSL_SESSION获取SSLSession

请求服务器上的客户端证书似乎是gRPC 没有办法,这对于互操作是必要的。考虑到SSL/TLS的工作方式,这并不完全是一个错误,但更多的是一个特性请求。

Java实现还没有将客户端证书作为一个完整的特性来支持。这将包括能够检索服务器上的客户端证书。请求客户端身份验证的能力必须是该功能的一部分。

Client是grpc完全打算支持的东西,但还没有被开发出来。

票数 6
EN

Stack Overflow用户

发布于 2017-05-18 09:11:07

要更新现有的答案,现在可以访问服务器端的SSLSession,它为客户端证书提供句柄。github项目( Security.mdhttps://github.com/grpc/grpc-java/blob/master/SECURITY.md)的Security.md文件给出了一个显式示例,在互TLS一节中,说明了如何这样做。

在编写本报告时,该文件引用了一个不存在的常量(ServerCall.SSL_SESSION_KEY),但我为此创建了一个问题,其中包含一个工作机制(https://github.com/grpc/grpc-java/issues/3013.)。现在,这个问题解决后,我的解决办法不再必要了,您可以按照Security.md的描述:

要获得客户端证书,您必须做什么:

实现ServerInterceptor

代码语言:javascript
复制
public class MyInterceptor implements ServerInterceptor {
    @Override
    public <ReqT, RespT> Listener<ReqT> interceptCall(ServerCall<ReqT, RespT> call, Metadata headers, ServerCallHandler<ReqT, RespT> next) {
        String subjectDn = null;
        try {
            SSLSession sslSession = (SSLSession) call.attributes().get(Grpc.TRANSPORT_ATTR_SSL_SESSION););
            // sslSession.getPeerCertificates(); contains the certificates, you are looking for 
            }
        } catch (SSLPeerUnverifiedException e) {
            // do what you need to do
        }
        return next.startCall(call, headers);
    }
}

并将其插入您的Server

代码语言:javascript
复制
server = NettyServerBuilder.forPort(port)
                    .sslContext(context)
                    .addService(ServerInterceptors.intercept(new MyServiceImpl(), new MyInterceptor()))
                    .build();

Security.md还告诉您如何将SSLSession注入到上下文中,以便在MyServiceImpl方法中对其有一些处理,从而实现要调用的远程过程。

请注意,这是实验性API,所以要小心使用它。

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32222389

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档