为什么我在使用HttpURLConnection时得到证书错误,而在使用SSLSocket时没有?如何使HTTPS调用工作?

hivapdat  于 2023-08-06  发布在  其他
关注(0)|答案(2)|浏览(112)

我不明白我从这段代码中得到的结果。
代码如下:

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调用以不抛出错误?是否对同一服务器的每个调用都在搜索两个不同的信任存储库?

tzdcorbm

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()不会在出错时抛出异常。相反,它返回一个布尔结果,您必须显式检查该结果。

wlzqhblo

wlzqhblo2#

SSL是一种加密协议。HTTPS使用HTTP over SSL-它将HTTP数据作为有效负载嵌入到SSL数据中。
如果您想使用HTTPS,就不能直接使用SSL。标准HTTP库都支持https,如果url的方案是https,它们将自动使用https。

相关问题