Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/370.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何使用X509证书通过HttpsURLConnection进行POST请求?_Java_Post_Ssl_Https - Fatal编程技术网

Java 如何使用X509证书通过HttpsURLConnection进行POST请求?

Java 如何使用X509证书通过HttpsURLConnection进行POST请求?,java,post,ssl,https,Java,Post,Ssl,Https,我有 自签名服务器证书(来自需要与之通信的第三方组织) 我的客户端证书,包含此服务器证书签名的密钥 现在我需要使用这些证书通过HTTPS发送POST请求。 在浏览器中安装https后,我在Internet Explorer中测试了https连接: 服务器证书-进入受信任的CA 客户证书-进入个人证书 在java中,直到现在我都使用neu242在回答中给出的代码,即接受任何证书。但现在服务器端确实接受了这一点,即SSL握手失败 多亏了,我尝试在getAcceptedIssuers中返回服务器证书,

我有

  • 自签名服务器证书(来自需要与之通信的第三方组织)
  • 我的客户端证书,包含此服务器证书签名的密钥
  • 现在我需要使用这些证书通过HTTPS发送POST请求。 在浏览器中安装https后,我在Internet Explorer中测试了https连接:

  • 服务器证书-进入受信任的CA
  • 客户证书-进入个人证书
  • 在java中,直到现在我都使用neu242在回答中给出的代码,即接受任何证书。但现在服务器端确实接受了这一点,即SSL握手失败

    多亏了,我尝试在
    getAcceptedIssuers
    中返回服务器证书,但没有成功。它抛出

    javax.net.ssl.SSLHandshakeException:收到致命警报:握手失败

    就在
    getAcceptedIssuers
    返回之后

    public X509Certificate[] getAcceptedIssuers() {
        try {
            X509Certificate scert;
            try (InputStream inStream = new FileInputStream("..\\server.crt")) {
                CertificateFactory cf = CertificateFactory.getInstance("X.509");
                scert = (X509Certificate) cf.generateCertificate(inStream);
            }                        
            return new X509Certificate[]{scert};
        } catch (Exception ex) {
            writeLogFile(ex.getMessage());
            return new X509Certificate[]{};
        }
    }
    
    我想我应该以某种方式指定客户机证书,但找不到任何方法。 当然,我可能错了


    希望有人能给我指引正确的方向。

    最后我终于成功了

    由于服务器证书是自签名的,所以我必须将其放入信任库中。为了避免将其添加到常见的JRE cacerts中,我使用以下命令将其放在单独文件中的信任库中(感谢:

    然后,我使用获得的信任库和包含密钥的客户端证书来初始化密钥库,并将它们指定给SSL上下文(感谢):

    我还必须指定
    主机名验证程序
    ,因为与服务器证书和此服务器的url存在一些不一致:

    HostnameVerifier allHostsValid = new HostnameVerifier() {
        public boolean verify(String hostname, SSLSession session) {
            //...
        }
    };
    
    HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
    
    就是这样,更简单的是:

    url = new URL(targetURL);
    
    connection = (HttpsURLConnection) url.openConnection();            
    connection.setRequestMethod("POST");
    connection.setRequestProperty("Content-Type", 
                                  "application/x-www-form-urlencoded;charset=utf-8");
    connection.setRequestProperty("Accept", "application/x-www-form-urlencoded");
    connection.setRequestProperty("Accept-Charset", "UTF-8");
    connection.setRequestProperty("Content-Length", 
                                  Integer.toString(Data.getBytes("utf8").length));
    connection.setDoInput(true);
    connection.setDoOutput(true);
    
    connection.getOutputStream().write(Data.getBytes("utf8"));
    // read response...
    

    握手是在客户端还是在服务器端失败?是否可以使用附加的jvm参数
    -Djavax.net.debug=all
    运行服务器和客户端,并共享控制台输出?
    HostnameVerifier allHostsValid = new HostnameVerifier() {
        public boolean verify(String hostname, SSLSession session) {
            //...
        }
    };
    
    HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
    
    url = new URL(targetURL);
    
    connection = (HttpsURLConnection) url.openConnection();            
    connection.setRequestMethod("POST");
    connection.setRequestProperty("Content-Type", 
                                  "application/x-www-form-urlencoded;charset=utf-8");
    connection.setRequestProperty("Accept", "application/x-www-form-urlencoded");
    connection.setRequestProperty("Accept-Charset", "UTF-8");
    connection.setRequestProperty("Content-Length", 
                                  Integer.toString(Data.getBytes("utf8").length));
    connection.setDoInput(true);
    connection.setDoOutput(true);
    
    connection.getOutputStream().write(Data.getBytes("utf8"));
    // read response...