java-CertificateException:找不到与ssl.someUrl.de匹配的名称

我正在尝试使用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()));

我在第三行出现错误:(找不到与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 64位

fehrlich asked 2020-07-28T18:07:46Z
6个解决方案
61 votes

您似乎要连接的服务器的证书与其主机名不匹配。

当HTTPS客户端连接到服务器时,它将验证证书中的主机名是否与服务器的主机名匹配。 证书受信任还不够,它还必须与您要交谈的服务器匹配。 (以此类推,即使您相信一本护照是合法的,您仍然必须检查它是您要与之交谈的人的护照,而不仅仅是您会相信的一本护照。)

在HTTP中,这是通过检查以下内容来完成的:

  • 证书包含与主机名匹配的DNS使用者替代名称(这是标准扩展名)条目;

  • 否则,您的主题专有名称的最后一个CN(如果需要,这是主名称)与主机名匹配。 (请参阅RFC2818。)

没有证书就很难说出主题的替代名称是什么(尽管,如果您连接浏览器并更详细地检查其内容,则应该可以看到它。)主题专有名称似乎是:

EMAILADDRESS=info@plesk.com, CN=plesk, OU=Plesk, O=Parallels, L=Herndon, ST=Virginia, C=US

(因此,如果您还没有使用DNS:ssl.someUrl.de的使用者替代名称,则它应该是CN = ssl.someUrl.de而不是CN = plesk;我的猜测是您没有。)

您可以使用HttpsURLConnection.setHostnameVerifier(..)绕过主机名验证。 编写一个基于验证的自定义HostnameVerifier并不难,尽管我建议仅在证书特别是与之相关的证书时这样做。 您应该能够使用SSLSession参数及其getPeerCertificates()方法获得该信息。

(此外,由于您仍在使用默认值,因此您无需按照完成操作的方式设置javax.net.ssl。*属性。)

另外,如果您可以控制要连接的服务器及其证书,则可以为其创建一个证书,该证书与上面的命名规则相匹配(CN应该足够,尽管主题备用名称是一个改进)。 如果自签名证书足以满足您的名称要求,请确保其公用名(CN)是您要与之交谈的主机名(没有完整的URL,只有主机名)。

Bruno answered 2020-07-28T18:08:39Z
28 votes

在Java 8中,您可以使用以下代码跳过服务器名称检查:

HttpsURLConnection.setDefaultHostnameVerifier ((hostname, session) -> true);

但是,这只能在开发中使用!

jamming answered 2020-07-28T18:09:04Z
14 votes

我创建了一个方法fixUntrustCertificate(),因此当我处理不在受信任CA中的域时,可以在请求之前调用该方法。 该代码将在java1.4之后生效。 此方法适用于所有主机:

public void fixUntrustCertificate() throws KeyManagementException, NoSuchAlgorithmException{


        TrustManager[] trustAllCerts = new TrustManager[]{
            new X509TrustManager() {
                public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                    return null;
                }

                public void checkClientTrusted(X509Certificate[] certs, String authType) {
                }

                public void checkServerTrusted(X509Certificate[] certs, String authType) {
                }

            }
        };

        SSLContext sc = SSLContext.getInstance("SSL");
        sc.init(null, trustAllCerts, new java.security.SecureRandom());
        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());

        HostnameVerifier allHostsValid = new HostnameVerifier() {
            public boolean verify(String hostname, SSLSession session) {
                return true;
            }
        };

        // set the  allTrusting verifier
        HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
}
Cassio Seffrin answered 2020-07-28T18:09:25Z
4 votes

我在这里找到了很好的解决方法:[http://www.mkyong.com/webservices/jax-ws/java-security-cert-certificateexception-no-name-matching-localhost-found/]

但是我的问题有点不同,解决方法也不同。

Web服务位于远程主机上。例如:[https://some.remote.host/MyWebService?wsdl]

但是它只能由IP用于任何客户端,但是证书是为域创建的:some.remote.host(CN = some.remote.host)。 而且该域无法通过IP解析,因为它未在DNS中显示)。

因此出现了相同的问题:如果我使用IP通过ssl连接到Web服务,则无法通过证书CN = some.remote.host来访问它,并且它不等于我指定的主机名(即主机IP) 。

我已经通过将此主机名与/ etc / hosts文件中的IP匹配来解决了该问题。该问题已解决。

但是,如果将Web Service托管在localhost应用服务器上,它会认为应该像mkyong在他的文章中描述的那样解决。

Zaur_M answered 2020-07-28T18:10:12Z
1 votes

服务器名称应与创建证书时输入的名字/姓氏相同

user2181029 answered 2020-07-28T18:10:32Z
1 votes

如果您正在寻找Kafka错误,则可能是因为Kafka版本从1.x升级到2.x。

javax.net.ssl.SSLHandshakeException:常规SSLEngine问题... javax.net.ssl.SSLHandshakeException:常规SSLEngine问题... java.security.cert.CertificateException:未找到与***相匹配的名称

要么

[Producer clientId = producer-1]由于以下原因,连接到节点-2的身份验证失败:SSL握手失败

ssl.endpoint.identification.algorithm的默认值已更改为https,它执行主机名验证(否则可能会发生中间人攻击)。 将ssl.endpoint.identification.algorithm设置为空字符串以恢复以前的行为。 Apache Kafka 2.0.0中的显着更改

解:SslConfigs.SSL_ENDPOINT_IDENTIFICATION_ALGORITHM_CONFIG,“”

Senchan Sue answered 2020-07-28T18:11:15Z
translate from https://stackoverflow.com:/questions/3093112/certificateexception-no-name-matching-ssl-someurl-de-found