我不明白我从这段代码中得到的结果。
代码如下:
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, null, null);
SSLSocketFactory factory = context.getSocketFactory();
try {
System.out.println("Starting SSL handshake...");
SSLSocket socket = (SSLSocket) factory.createSocket(host, port);
socket.setSoTimeout(10000);
socket.startHandshake();
socket.close();
System.out.println("No errors, certificate is already trusted");
} catch (SSLException e) {
e.printStackTrace(System.out);
}
try {
System.out.println("\nStarting an https connection to the same address...");
HttpURLConnection http = (HttpURLConnection)new URL("https://" + host + ":" + port).openConnection();
http.setRequestMethod("POST");
System.out.println("Response code: " + http.getResponseCode());
} catch (SSLException e) {
e.printStackTrace(System.out);
}
字符串
结果如下:
Starting SSL handshake...
No errors, certificate is already trusted
Starting an https connection to the same address...
javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No name matching xxxxxxxxxxxx found (NOTE: xxxxxxxxxxx is the value of 'host')
at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1946)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:316)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:310)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1640)
at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:223)
at sun.security.ssl.Handshaker.processLoop(Handshaker.java:1037)
at sun.security.ssl.Handshaker.process_record(Handshaker.java:965)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1064)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1367)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1395)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1379)
at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:559)
at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1570)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1498)
at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:480)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:352)
Caused by: java.security.cert.CertificateException: No name matching dqdev4607vm02 found
at sun.security.util.HostnameChecker.matchDNS(HostnameChecker.java:231)
at sun.security.util.HostnameChecker.match(HostnameChecker.java:96)
at sun.security.ssl.X509TrustManagerImpl.checkIdentity(X509TrustManagerImpl.java:459)
at sun.security.ssl.X509TrustManagerImpl.checkIdentity(X509TrustManagerImpl.java:440)
at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:209)
at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:132)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1622)
... 14 more
型
我不明白为什么套接字在我的信任存储中找到了证书,而https连接却没有。如果你能帮忙的话,我将不胜感激。
好了,根据目前收到的答案,下面是对正在发生的事情的解释。
我已经从几年前在互联网上找到的一个类中提取了SSL代码,以便将新的证书添加到我的信任存储中。如果SSL失败,它会下载证书并将其添加到我的商店。然后,当我再次运行同一个类时,第一次“尝试”将通过,因为证书现在在我的存储中。
但是当我试图用https访问同一个网站时,我得到了错误。响应“Steffen Ullrich”的回答,主机和端口是相同的。这不是一个有一个子域的问题,另一个没有。
所以新的问题是,如何更改HTTPS调用以不抛出错误?是否对同一服务器的每个调用都在搜索两个不同的信任存储库?
2条答案
按热度按时间tzdcorbm1#
我不明白为什么套接字在我的信任存储中找到了证书,而https连接却没有。如果你能帮忙的话,我将不胜感激。
问题不在于在信任存储中查找根CA-这在两种情况下都有效。HttpURLConnection的问题在于证书的主机名验证。此处证书的主题/SAN与您在URL中使用的主机名不匹配,即例如,证书是
example.org
的,但在URL中使用whatever.example.org
访问站点。... CertificateException:未找到与xxxxxxxxxxxx匹配的名称(注:xxxxxxxxx是'host'的值)
使用SSLSocket不会出现此错误,因为那里没有进行主机名验证。
来自Security with network protocols - Warnings about using SSLSocket directly:
注意:SSLSocket不进行主机名校验。由您的应用自行执行主机名验证,最好是使用预期的主机名调用getDefaultHostnameVerifier()。另外,要注意HostnameVerifier.verify()不会在出错时抛出异常。相反,它返回一个布尔结果,您必须显式检查该结果。
wlzqhblo2#
SSL是一种加密协议。HTTPS使用HTTP over SSL-它将HTTP数据作为有效负载嵌入到SSL数据中。
如果您想使用HTTPS,就不能直接使用SSL。标准HTTP库都支持https,如果url的方案是https,它们将自动使用https。