向服务器发送请求时出现 javax.net.ssl.SSLHandshakeException : java. security.cert.CertPathValidatorException

标签 java android ssl https httpsurlconnection

我正在尝试连接到服务器并使用以下代码向其发送基于 HTTPS 的请求:

// create the URL with the target URL specified
URL url = new URL(vTargetURL);

// create a HTTP connection to the URL specified
HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();

// set the timeout for the request
urlConnection.setReadTimeout(30000);

//add request header
urlConnection.setRequestMethod("POST");
urlConnection.setRequestProperty("Content-Length", String.valueOf(vRequestXML.length()));
for (HashMap.Entry<String, String> entry : vHttpHeaders.entrySet()) {           
    urlConnection.setRequestProperty(entry.getKey(), entry.getValue());
}


// send the request
DataOutputStream dataOutputStream = new DataOutputStream(urlConnection.getOutputStream());
dataOutputStream.writeBytes(vRequestXML);
dataOutputStream.flush();
dataOutputStream.close();

// read the response
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
String inputLine;

StringBuffer response = new StringBuffer();         
while ((inputLine = bufferedReader.readLine()) != null) {
    response.append(inputLine);
}                   
bufferedReader.close();

我面临的问题是我的代码在声明处失败了

DataOutputStream dataOutputStream = new DataOutputStream(urlConnection.getOutputStream());

有异常(exception)

javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.

我只知道有一些与服务器证书相关的问题。我可以使用以下代码绕过此问题:

final HostnameVerifier DO_NOT_VERIFY = new HostnameVerifier() {
    @Override
    public boolean verify(String hostname, SSLSession session) {
        return true;
    }
};  

urlConnection.setHostnameVerifier(DO_NOT_VERIFY);

// Create a trust manager that does not validate certificate chains
TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {

    public java.security.cert.X509Certificate[] getAcceptedIssuers() {
        return new java.security.cert.X509Certificate[] {};
    }

    public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
    }

    public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
    }
}};

// Install the all-trusting trust manager
try {
    SSLContext sc = SSLContext.getInstance("TLS");
    sc.init(null, trustAllCerts, new java.security.SecureRandom());
    HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
}
catch (Exception e) {
    e.printStackTrace();
}

此外,当我检查这个 website 上的服务器地址时,我得到了以下错误

enter image description here

我知道信任所有主机并不能解决这个问题,但我无法得出结论我应该如何解决这些问题。具体我想了解:

  1. 出现这种异常的可能原因是什么。
  2. 我该如何解决这些问题。

感谢任何线索。

谢谢。

最佳答案

当您建立 HTTPS 连接时,您连接的服务器会发送他的证书以证明您获得了正确的服务器。该证书通常由另一个证书签名,或者由 CA(证书颁发机构)的证书签名,或者仅由另一个证书签名,后者又被签名。不管这条链有多长,您都可以在底部找到 CA 的证书。

怎么知道这个CA证书没问题? Java 通过将所有可信 CA 的证书存储在 keystore (cacerts) 中来解决这个问题。

您遇到的错误很可能是由不在 keystore 中的 CA 签署的证书造成的。它可以是自签名证书(证书本身充当自己的 CA)、由某个公司的内部 CA 或小型未知 CA 签名的证书。

您必须决定是否要信任此 CA 签署的所有证书。在这种情况下,获取 CA 证书,并将其放入您的 cacerts 文件中。

不过,我不知道如何在 Android 上执行此操作。执行此操作的标准 Java 工具是 keytool。

关于向服务器发送请求时出现 javax.net.ssl.SSLHandshakeException : java. security.cert.CertPathValidatorException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27438034/

相关文章:

守护进程运行时的 Java 命令行

java - 有没有一种简单的方法可以在 Jhipster 微服务网关上添加社交登录?

java - 禁用预先选中的复选框警报对话框 android java

android - 从 FragmentActivity 获取 Fragment 的 View

javascript - 是否可以让来自 NGINX(端口 443)的 SSL 页面也在端口 3000 上使用 socket.io(通过 Node.js)

java - 私有(private)方法or内部类,该用哪个

java - 使用 Jdk8Module 反序列化 LocalDate 可选会引发错误

android - Kotlin "Do not concatenate text displayed with setText. Use resource string with placeholders. "

php - 如何在html5网站和wbeserver之间使用ssl建立安全连接

apache - 如何在续订 SSL 固定机制时不更改 key