sun.security.validator.ValidatorException

时间:2017-04-08 14:46:59

标签: java https

我有桌面应用。 任务是添加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();
    }
}

服务器具有签名认证。 我如何改进或实现与服务器一起工作的另一种方式?

2 个答案:

答案 0 :(得分:0)

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

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

说明JCA如何支持SSL / TLS,而SSL / TLS又用于' S'在HTTPS中可以找到: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并打开没有Verifier的连接。

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());

答案 1 :(得分:0)

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

  1. 您的SSLContext配置错误。最好不要设置SSLContext 1 。这将导致SSL堆栈使用默认值,该堆栈将使用JRE密钥库中的受信任根。
  2. 您的HostnameVerifier将接受任何主机名,这使得添加一个主机名毫无意义。 (这是默认验证程序的作用。)
  3. 如果要使用HostnameVerifier,则必须在建立连接之前设置它。这样做的方法是使用静态setDefaultHostnameVerifier方法。
  4. 代码可能泄漏Socket文件描述符。读者应该在finally块中关闭。
  5. 1 - 如果您需要覆盖密钥库中的内容或执行与正常行为不同的其他操作,则可以使用SSLContext。例如,您可能希望关闭某个已过期证书的已知可信服务器上的验证。或者您可能希望不信任给定的根CA.