【问题标题】:How to programmatically add self signed certificate for making a HTTPS request from java code?如何以编程方式添加自签名证书以从 Java 代码发出 HTTPS 请求?
【发布时间】:2013-12-07 14:06:37
【问题描述】:

以下代码 sn-p 是从HTTP URL 获取JSon 响应:

private static void getJson(String location) {
    try {
        try {
            createSSLSocket();
            URL url = new URL(
                    "https://abc.com/key/one");
            HttpURLConnection conn = (HttpURLConnection) url
                    .openConnection();
            conn.setRequestMethod("GET");
            conn.setRequestProperty("Accept", "application/json");
            if (conn.getResponseCode() != 200) {
                throw new RuntimeException("Failed : HTTP error code : "
                        + conn.getResponseCode());
            }
            BufferedReader br = new BufferedReader(new InputStreamReader(
                    (conn.getInputStream())));
            String output;
            System.out.println("Output from Server .... \n");
            while ((output = br.readLine()) != null) {
                System.out.println(output);
            }
            conn.disconnect();

        } catch (MalformedURLException e) {
            e.printStackTrace();

        } catch (IOException e) {
            e.printStackTrace();

        }
    } catch (Exception ex) {
        ex.printStackTrace();
    }

}

但它会抛出 SSLHandshaking 异常,因为我没有在代码中添加自签名认证异常。我在C# 中做到了这一点,但在 java 中没有。我应该执行哪些步骤?需要你的建议:)

提前致谢。

【问题讨论】:

  • 你的意思是服务器证书是自签名的,这就是连接失败的原因吗? SSLHandshakeException 中包含的失败原因是什么?
  • @jcs 是的,服务器端连接是自签名的,这是错误:unable to find valid certification path to requested target
  • @Jcs 我们可以用程序来做吗?
  • 是的,我添加了一个带有代码 sn-p 的答案。

标签: java ssl https get ssl-certificate


【解决方案1】:

要为自签名证书添加信任,您可以创建一个truststore java 密钥库文件并将javax.net.ssl.trustStore 属性设置为指向该文件。 openConnection 方法将检查信任库以查看证书是否可以信任。

要创建信任库文件,您可以使用 keytool 命令,该命令是 JDK 的一部分,应该位于您的 JAVA_HOME/bin 目录中。

keytool -import -file yourcert.cert -alias abc -keystore truststore.jks

如果要编辑信任库,该命令将提示您输入密码。输入密码后,它将创建一个truststore.jks 文件。要以编程方式在 Java 中设置信任库,您可以使用 -Djavax.net.ssl.trustStore=/path/truststore.jks 将其作为属性传递,也可以调用 System.setProperty

System.setProperty("javax.net.ssl.trustStore", "/path/truststore.jks");

要查看 Java 使用的 ssl 属性,请查看 here

【讨论】:

    【解决方案2】:

    您可以将HttpsURLConnection 套接字工厂配置为接受所有证书而无需任何验证:

    private class TrustAll implements X509TrustManager
    {
        public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException
        {
        }
    
        public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException
        {
        }
    
        public X509Certificate[] getAcceptedIssuers()
        {
            return new X509Certificate[0];
        }
    }
    
    SSLContext ctx = SSLContext.getInstance("TLS");
    ctx.init(null, new TrustManager[] { new TrustAll() }, null);
    HttpsURLConnection.setDefaultSSLSocketFactory(ctx.getSocketFactory());
    

    更新

    您只需在应用程序启动时调用此代码一次。所有使用URL.openConnection() 打开的 HTTPS 连接都将使用这个套接字工厂。另一种解决方案是在createSSLSocket() 方法体中添加此代码。

    【讨论】:

    • 感谢您的回答,但请您告诉我应该如何连接到 getJson 方法(有问题)?
    • 我更新了答案。实际上你没有太多代码需要改变。
    • 那之后我可以使用HttpURLConnection conn = (HttpURLConnection) url.openConnection();吗?
    • 是的,SSL套接字工厂是全局设置的
    • 请注意,这种技术根本不安全。你应该采纳@cyon 的建议。
    猜你喜欢
    • 2016-12-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-09
    • 2013-10-18
    • 1970-01-01
    • 1970-01-01
    • 2016-05-20
    相关资源
    最近更新 更多