如何在Netty处理程序中获取客户端证书以识别用户?

7

我成功地使用了2向SSL运行Netty(参见在Netty中建立2向SSL Handsake(客户端和服务器证书))。

但是,在我的某些处理器中,我需要知道谁在使用该应用程序。我发现我无法弄清楚如何在处理器中获取用户证书DN等信息。

我认为它应该在ChannelHandlerContext的某个位置可用,但实际上并不是这样。有什么建议吗?

我知道SSLEngine在某个地方可以访问它,但我没有看到关于在SSLEngine公共API中获取访问权限的任何信息。我知道它在握手操作中可以访问...但我该如何获取它呢?

3个回答

11

可以通过Pipeline/ChannelHandlerContext获取SSLEngine。

ChannelHandlerContext ctx = ...
SslHandler sslhandler = (SslHandler) ctx.channel().pipeline().get("ssl");
sslhandler.engine().getSession().getPeerCertificateChain()[0].getSubjectDN());

这允许您在处理程序对象中获取证书。请注意,在执行此操作时,SSL握手必须完成。否则,您将收到

javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated

异常。为了避免这种情况,您可以在处理程序中监听用户事件(在我们的案例中是HandshakeCompletionEvent),代码如下:

@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) {
    logger.info("userEventTriggered: {0}, Class: {1}", evt.toString(), evt.getClass());

    if (evt instanceof HandshakeCompletionEvent) {
        fetchCertificate(ctx);
    }
} 

9
SSLEngine.getSession().getPeerCertificateChain()。第零个条目是对等方自己的证书。

Play! 框架在其后台使用 netty,我想获取 SSL 客户端证书,如何获取当前的 SSLEngine? - Jaime Hablutzel

-1
我使用以下代码获取客户端证书和证书颁发者。希望这可以帮助到你。
 SslHandler sslHandler = (SslHandler) ctx.channel().pipeline().get("ssl");

 X509Certificate issuer = convert(sslHandler.engine().getSession().getPeerCertificateChain()[sslHandler.engine().getSession().getPeerCertificateChain().length -1]);

 System.out.println("issuer: " + issuer);


  public static java.security.cert.X509Certificate convert(javax.security.cert.X509Certificate cert) {
    try {
        byte[] encoded = cert.getEncoded();
        ByteArrayInputStream bis = new ByteArrayInputStream(encoded);
        java.security.cert.CertificateFactory cf
                = java.security.cert.CertificateFactory.getInstance("X.509");
        return (java.security.cert.X509Certificate)cf.generateCertificate(bis);
    } catch (java.security.cert.CertificateEncodingException e) {
    } catch (javax.security.cert.CertificateEncodingException e) {
    } catch (java.security.cert.CertificateException e) {
    }
    return null;
}

为什么?你已经有证书了。为什么要再次编码和解码它?convert()方法在这里是无意义的。 - user207421

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接