2

我需要忽略 PKIX 路径构建异常

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException:
PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderExc
ption: unable to find valid certification path to requested target

我知道如何通过编写自己的类来实现X509TrustManager我总是return trueisServerTrusted.

但这相当广泛。我的代码将成为更大项目的一部分。我不希望其他一切都因我更换信托经理而受到影响。

我总是要连接到一个固定的域名,即“www.myws.com”。我只想忽略与SSLHandshakeException“www.myws.com”的唯一连接。

这样的事情可能吗?

4

1 回答 1

1

2 个问题的答案几乎不可能相同,因为我认为 TrustMananger 根本不会获得服务器的域名。

实际上,信任管理器可以获得您所追求的主机名的名称。不过,这取决于许多因素。

  • 让我们假设您的客户端在 Java 7 上运行。

    如果您遵循与其他答案相同的方法,但使用 an X509ExtendedTrustManager(在 Java 7 中引入,而不是 plain X509TrustManager),您将获得额外的重载方法,这些方法也为您提供当前的SSLSocketSSLEngine

    使用实例SSLContext初始化时会使用这些方法X509ExtendedTrustManager,但当它是 plain 时不会使用X509TrustManager,因此它必须在进行这些调用之前检查类型(请参阅此答案末尾的快速测试,基于该答案中的代码)。

    我不确定这个行为是在哪里指定的 API。JSSE 参考指南中似乎没有关于这种X509ExtendedTrustManager类型检查的任何内容。确保使用扩展方法的一种方法是在您的 . (这也是 Java 7 中引入的一个特性。)SSLParameters

    从那里获得SSLSocketSSLEngine获得,您可以获得SSLSession和对等主机,因此您可以在那里执行检查。SSLSocket(请注意,如果创建的库或未SSLEngine使用将名称作为 a 传递的方法之一String,而是通过 a代替,则主机名可能与预期不完全匹配InetAddress。在这种情况下,您也会丢失 SNI。)

    然后,您可以在默认情况下使用这样的信任管理器SSLContext(使用setDefault(...))。

  • 如果您不想影响默认值SSLContext(这种调整的明智选择),您需要弄清楚您的客户端库如何在每个连接中使用不同的库。这完全取决于使用什么。

    对于传统的URLConnection,将其投射为一个HttpsURLConnection并设置为SSLSocketFactory您自定义的一个构建SSLContext


使用哪些方法取决于您是否实例化了 anX509ExtendedTrustManager或 a X509TrustManager

X509TrustManager customTm = new X509ExtendedTrustManager() {
    @Override
    public X509Certificate[] getAcceptedIssuers() {
        return finalTm.getAcceptedIssuers();
    }

    @Override
    public void checkServerTrusted(X509Certificate[] chain,
            String authType) throws CertificateException {
        System.out
                .println("Current method: checkServerTrusted(chain, authType)");
        finalTm.checkServerTrusted(chain, authType);
    }

    //@Override
    public void checkServerTrusted(X509Certificate[] chain,
            String authType, Socket socket) throws CertificateException {
        System.out
                .println("Current method: checkServerTrusted(chain, authType, socket)");
        finalTm.checkServerTrusted(chain, authType, socket);
    }

    //@Override
    public void checkServerTrusted(X509Certificate[] chain,
            String authType, SSLEngine engine)
            throws CertificateException {
        System.out
                .println("Current method: checkServerTrusted(chain, authType, engine)");
        finalTm.checkServerTrusted(chain, authType, engine);
    }

    // Same for client-related methods.
};
于 2013-09-25T16:26:55.677 回答