【问题标题】:How to get the client's certificate in jetty server when doing authentication进行身份验证时如何在码头服务器中获取客户端的证书
【发布时间】:2020-12-02 20:15:48
【问题描述】:

通过设置SslContextFactory.setNeedClientAuth(true)设置请求客户端认证的嵌入式Jetty服务器后,当客户端连接到jetty服务器两种情况下,认证成功和失败,如何获取客户端的证书信息?

我已阅读此reference,但我认为这仅适用于身份验证成功。 SecureRequestCustomizer.customize(...)似乎只有在客户端的证书信息认证成功后才会执行。

但是我想知道当码头服务器进行身份验证时,无论成功还是失败,有什么方法可以获取客户端的证书信息。然后即使这个客户端不被jetty sever信任,我也可以获取客户端的证书信息。

【问题讨论】:

    标签: ssl jetty embedded-jetty sslcontext


    【解决方案1】:

    欢迎使用 stackoverflow。

    当您设置了SslContextFactory.setNeedClientAuth(true) 时,这意味着您正在设置Java 级别javax.net.ssl.SSLParameters.setNeedClientAuth(true)

    这会影响新连接的 Java 级别 TLS/SSL 协商,并强制它们需要有效的客户端证书。

    如果失败,连接由 Java 本身在 TLS/SSL 握手级别终止,客户端甚至不会发送 HTTP 请求,Jetty 也没有参与此确定。

    正如您毫无疑问地已经注意到的那样,在SecureRequestCustomizer 中不会处理未能通过 TLS/SSL 级别客户端身份验证的连接。

    如果您希望看到成功的和失败的客户端通过 TLS/SSL 握手级别并到达您的各种 HTTP 处理程序,那么您必须关闭 SslContextFactory.setNeedClientAuth(true) 设置。但这意味着 Java JVM 的 TLS/SSL 层不执行客户端证书身份验证,您现在可以在自己的代码中执行这些相同的检查。这不会很好地工作。

    所以你可以选择......

    1. setNeedClientAuth(true) - 连接已通过身份验证,如果客户端证书失败则终止。客户端未创建任何 HTTP 请求。
    2. setNeedClientAuth(false) - 所有连接都成功且不执行身份验证,从而产生您可以处理的 HTTP 请求。

    如果您需要第 1 点,但第 2 点不可行,请考虑使用 org.eclipse.jetty.io.ssl.SslHandshakeListener 并只关注成功/失败的结果。

    创建您自己的此侦听器实现,并将其作为 bean 添加到您的服务器连接器。您将获得该事件源的活动javax.net.ssl.SSLEngine,您可以在其中询问您在连接失败后的各种详细信息(您甚至可以获取尝试连接的客户端的 IP 信息)

    【讨论】:

    • 非常感谢,这就是我想要的。
    • 嗨@Joakim,我试过了,但是当 ssl 握手失败时,我无法从 SSLEngine 获取任何信息。我得到了 SSLSession,SSLSession session = event.getSSLEngine().getSession();,但是当我用session.getPeerCertificates()session.getPeerCertificateChain() 获得其他信息时,它都会抛出javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated。当 ssl 握手正常时,我可以通过以上两种方法获取证书信息。你知道吗。非常感谢
    • 请注意 session.getPeerCertificateChain() 已弃用,使用 javadoc 中指示的推荐替代方案,并注意有关 SSLPeerUnverifiedException 含义的推荐路径上的 javadoc,尤其是在特定密码套件功能方面。
    • 我检查过,我使用了正确的密码,并尝试使用getPeerCertificates(),但仍然没有找到证书。这个方法的javadoc说SSLPeerUnverifiedException会被抛出if the peer's identity has not been verified。所以我担心身份验证失败时我无法获得对等身份。
    • 我尝试使用SSLContex初始化X509TrustManagerX509TrustManager.checkServerTrusted(X509Certificate[] var1, String var2)覆盖来启动SslContextFactory设置,在这种方法中我可以直接打印出证书信息,无论对等方是否经过身份验证或不是。幸运的是,这行得通。但是您是否预见到在 Jetty 中使用自制 SSLContext 会有任何风险
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-06-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多