【问题标题】:sun.security.validator.ValidatorExceptionsun.security.validator.ValidatorException
【发布时间】:2017-04-08 14:46:58
【问题描述】:

我有桌面应用程序。 任务是添加用于加载文件的 https 协议。 有一种方法

 static public void test(){
    try {
        SSLContext ctx = SSLContext.getInstance("TLS");
        ctx.init(new KeyManager[0], 
            new TrustManager[] {new X509TrustManager(){
                @Override public void checkClientTrusted(
                     X509Certificate[] arg0, String arg1) 
                throws CertificateException {}

                @Override public void checkServerTrusted(
                     X509Certificate[] arg0, String arg1) 
                throws CertificateException {}

                @Override public X509Certificate[] getAcceptedIssuers() {
                    return null;
                }}}, new SecureRandom());
        SSLContext.setDefault(ctx);

        URL url = null;

        url = new URL("https://tlauncher.org/repo/test" +
                      "/ConfigPreMasterSALF-2.18.json");

        HttpsURLConnection conn = (HttpsURLConnectio) url.openConnection();
        conn.setHostnameVerifier(new HostnameVerifier() {
           @Override public boolean verify(String arg0, SSLSession arg1) {
              return true;
           }
        });
        BufferedReader reader = new BufferedReader(new InputStreamReader(
            conn.getInputStream(),"utf8"));

        StringBuilder response = new StringBuilder();
        String line;
        while ((line = reader.readLine()) != null) {
            response.append(line);
        }
        reader.close();
        System.out.println(response.toString());
        conn.disconnect();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

服务器具有签名证书。 我怎样才能改进或实现与服务器一起工作的另一种方式?

【问题讨论】:

    标签: java https


    【解决方案1】:

    从 getAcceptedIssuers 返回 null 会告诉客户端代码中的验证方法不信任 HTTPS 服务器持有的任何证书。这样的客户端永远不会信任服务器并且无法建立连接。要使其正常工作,您应该返回证书颁发机构 (CA) 证书,该证书是用于签署服务器证书的颁发机构。我们称该 CA 证书为信任根。无论如何,你在这里做的很多步法,而 Java 有预建的设施,你可以在网上找到很多例子。

    您使用的库称为 JCA Java 密码体系结构,它具有存储此类证书以供将来使用的方法。使用 JCA 的密钥工具将信任根导入密钥库并在打开与服务器的安全连接之前激活该密钥库。

    JCA 如何支持 SSL/TLS 的说明,而 SSL/TLS 又用于 HTTPS 中的“S”,可以在这里找到:http://docs.oracle.com/javase/7/docs/technotes/guides/security/crypto/CryptoSpec.html#SSLTLS 它还更详细地介绍了 KeyManager、TrustManager 和 KeyStore 设施。

    无论如何,我已经尝试过您将代码指向的 URL,它在 Firefox 浏览器和 Java 中也可以正常工作。它带有来自 COMODO CA 的有效 SSL 证书。如果这是您尝试获取的真实 URL,您可以完全忘记 JCA,跳过设置 SSLContext 并在没有验证程序的情况下打开连接。

    URL url = new URL("https://tlauncher.org/repo/test/ConfigPreMasterSALF-2.18.json");
    HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
    BufferedReader reader = new BufferedReader(new InputStreamReader(
            conn.getInputStream(),"utf8"));
    StringBuilder response = new StringBuilder();
    String line;
    while ((line = reader.readLine()) != null) {
        response.append(line);
    }
    reader.close();
    System.out.println(response.toString());
    

    【讨论】:

      【解决方案2】:

      以下是您当前版本的一些问题:

      1. 您的 SSLContext 配置错误。你最好不要设置 SSLContext1。这将导致 SSL 堆栈使用默认堆栈,该堆栈将使用 JRE 密钥库中的受信任根。
      2. 您的 HostnameVerifier 将接受任何主机名,这使得添加一个毫无意义。 (这是默认验证器所做的。)
      3. 如果要使用 HostnameVerifier,则必须在建立连接之前进行设置。方法是使用静态setDefaultHostnameVerifier 方法。
      4. 代码可能会泄漏 Socket 文件描述符。阅读器应在 finally 块中关闭。

      1 - 如果您需要覆盖密钥库中的内容或执行与正常行为不同的其他操作,则可以使用 SSLContext。例如,您可能希望在某些具有过期证书的已知受信任服务器上关闭验证。或者您可能想要不信任给定的根 CA。

      【讨论】:

        猜你喜欢
        • 2018-11-09
        • 2017-07-03
        • 2021-06-26
        • 2015-09-18
        • 2011-12-17
        相关资源
        最近更新 更多