我正在尝试使用 Java 通过 ssl 连接到我的一台服务器。我尝试了很多选择,这是我最好的尝试:
我使用推荐脚本生成 jssecacerts:http: //blogs.oracle.com/andreas/resource/InstallCert.java 使用命令:java InstallCert ssl.someUrl.de changeit
在此之后,我第二次执行了命令:
Loading KeyStore jssecacerts...
Opening connection to ssl.someUrl.de:443...
Starting SSL handshake...
No errors, certificate is already trusted
Server sent 1 certificate(s):
1 Subject EMAILADDRESS=info@plesk.com, CN=plesk, OU=Plesk, O=Parallels, L=Hernd
on, ST=Virginia, C=US
Issuer EMAILADDRESS=info@plesk.com, CN=plesk, OU=Plesk, O=Parallels, L=Hernd
on, ST=Virginia, C=US
sha1 f1 0d 2c 54 05 e1 32 19 a0 52 5e e1 81 6c a3 a5 83 0d dd 67
md5 f0 b3 be 5e 5f 6e 90 d1 bc 57 7a b2 81 ce 7d 3d
Enter certificate to add to trusted keystore or 'q' to quit: [1]
我将文件复制到默认目录,并将证书加载到 Java trustStore
System.setProperty("javax.net.ssl.trustStore", "C:\\Program Files (x86)\\Java\\jre6\\lib\\security\\jssecacerts");
System.setProperty("javax.net.ssl.trustStorePassword","changeit");
然后我尝试连接
URL url = new URL("https://ssl.someUrl.de/");
URLConnection conn = url.openConnection();
BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
我在第 3 行得到错误:(找不到与 ssl.someUrl.de 匹配的名称)
javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No name matching ssl.someUrl.de found
这是默认 plesk 证书的原因还是其他错误?
设置:JRE 6.20、Netbeans 6.8、Windows7 64bit
原文由 fehrlich 发布,翻译遵循 CC BY-SA 4.0 许可协议
看起来您尝试连接的服务器的证书与其主机名不匹配。
当 HTTPS 客户端连接到服务器时,它会验证证书中的主机名是否与服务器的主机名匹配。仅信任证书是不够的,它还必须与您要与之交谈的服务器匹配。 (打个比方,即使您相信护照是合法的,您仍然必须检查它是否是您想与之交谈的人的护照,而不仅仅是您认为合法的任何护照。)
在 HTTP 中,这是通过检查以下内容来完成的:
证书包含与主机名匹配的 DNS 主题备用名称(这是标准扩展名)条目;
否则,您的主题可分辨名称的最后一个 CN(如果需要,这是主名称)与主机名匹配。 (参见 RFC 2818。)
如果没有证书,很难说出主题备用名称是什么(尽管,如果您连接浏览器并更详细地检查其内容,您应该能够看到它。)主题可分辨名称似乎是:
(因此,如果您还没有带有 DNS:ssl.someUrl.de 的主题替代名称,则需要 CN=ssl.someUrl.de 而不是 CN=plesk;我猜您没有。)
您可以使用 HttpsURLConnection.setHostnameVerifier(..) 绕过主机名验证。编写一个绕过验证的自定义 HostnameVerifier 应该不会太难,尽管我建议仅在证书是此处特别关注的证书时才这样做。您应该能够使用 SSLSession 参数及其 getPeerCertificates() 方法来获得它。
(此外,您不需要按照您所做的方式设置 javax.net.ssl.* 属性,因为无论如何您都在使用默认值。)
或者,如果您可以控制要连接的服务器及其证书,则可以创建与上述命名规则匹配的证书(CN 应该足够了,尽管主题备用名称是一种改进)。如果自签名证书足以满足您的命名要求,请确保其公用名 (CN) 是您尝试与之通信的主机名(不是完整的 URL,只有主机名)。