Java CertificateException:找不到与 ssl.someUrl.de 匹配的名称
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3093112/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
CertificateException: No name matching ssl.someUrl.de found
提问by fehrlich
I'm trying to connect to one of my servers through ssl, with Java. I tried a lot of options here is my best try:
我正在尝试使用 Java 通过 ssl 连接到我的一台服务器。我尝试了很多选择,这是我最好的尝试:
I generate a jssecacerts with the recommendet script: http://blogs.oracle.com/andreas/resource/InstallCert.javawith the command: java InstallCert ssl.someUrl.de changeit
我使用推荐脚本生成一个 jssecacerts:http: //blogs.oracle.com/andreas/resource/InstallCert.java使用命令:java InstallCert ssl.someUrl.de changeit
after this I did the command a second time:
在此之后,我第二次执行命令:
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 [email protected], CN=plesk, OU=Plesk, O=Parallels, L=Hernd
on, ST=Virginia, C=US
Issuer [email protected], 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]
I copied the file to the default directory and I loaded the certificate in Java trustStore
我将文件复制到默认目录并将证书加载到 Java trustStore
System.setProperty("javax.net.ssl.trustStore", "C:\Program Files (x86)\Java\jre6\lib\security\jssecacerts");
System.setProperty("javax.net.ssl.trustStorePassword","changeit");
Then I try to connect
然后我尝试连接
URL url = new URL("https://ssl.someUrl.de/");
URLConnection conn = url.openConnection();
BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
And I get Error on 3rd line: (No name matching ssl.someUrl.de found)
我在第 3 行收到错误:(找不到与 ssl.someUrl.de 匹配的名称)
javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No name matching ssl.someUrl.de found
Is this cause of the default plesk certificate or is something else wrong?
这是默认 plesk 证书的原因还是其他错误?
Setup: JRE 6.20, Netbeans 6.8, Windows7 64bit
设置:JRE 6.20、Netbeans 6.8、Windows7 64 位
采纳答案by Bruno
It looks like the certificate of the server you are trying to connect to doesn't match its hostname.
您尝试连接的服务器的证书似乎与其主机名不匹配。
When an HTTPS client connects to a server, it verifies that the hostname in the certificate matches the hostname of the server. It's not enough for a certificate to be trusted, it has to match the server you want to talk to too. (As an analogy, even if you trust a passport to be legitimate, you still have to check that it's the one for the person you want to talk to, not just any passport you would trust to be legitimate.)
当 HTTPS 客户端连接到服务器时,它会验证证书中的主机名是否与服务器的主机名匹配。仅仅信任证书是不够的,它还必须与您想要与之交谈的服务器相匹配。(打个比方,即使您相信护照是合法的,您仍然必须检查它是否适合您要与之交谈的人,而不仅仅是您认为是合法的任何护照。)
In HTTP, this is done by checking that:
在 HTTP 中,这是通过检查以下内容来完成的:
the certificate contains a DNS subject alternative name (this is a standard extension) entry matching the hostname;
failing that, the last CN of your subject distinguished name (this is the main name if you want) matches the hostname. (See RFC 2818.)
证书包含与主机名匹配的 DNS 主题备用名称(这是标准扩展名)条目;
如果失败,主题专有名称的最后一个 CN(如果需要,这是主名称)与主机名匹配。(参见 RFC 2818。)
It's hard to tell what the subject alternative name is without having the certificate (although, if you connect with your browser and check its content in more details, you should be able to see it.) The subject distinguished name seems to be:
在没有证书的情况下很难判断主题备用名称是什么(尽管,如果您连接浏览器并查看其内容的更多详细信息,您应该能够看到它。)主题专有名称似乎是:
[email protected], CN=plesk, OU=Plesk, O=Parallels, L=Herndon, ST=Virginia, C=US
(It would thus need to be CN=ssl.someUrl.de instead of CN=plesk, if you don't have a subject alternative name with DNS:ssl.someUrl.de already; my guess is that you don't.)
(因此,它需要是 CN=ssl.someUrl.de 而不是 CN=plesk,如果您还没有带有 DNS:ssl.someUrl.de 的主题备用名称;我猜您没有。)
You may be able to bypass the hostname verification using HttpsURLConnection.setHostnameVerifier(..). It shouldn't be too hard to write a custom HostnameVerifier that bybasses the verification, although I would suggest doing it only when the certificate its the one concerned here specifically. You should be able to get that using the SSLSession argument and its getPeerCertificates() method.
您可以使用HttpsURLConnection.setHostnameVerifier(..)绕过主机名验证。编写一个基于验证的自定义 HostnameVerifier 应该不会太难,尽管我建议仅当证书是此处特别关注的证书时才这样做。您应该能够使用 SSLSession 参数及其 getPeerCertificates() 方法获得它。
(In addition, you don't need to set the javax.net.ssl.* properties the way you've done it, since you're using the default values anyway.)
(此外,您不需要像以前那样设置 javax.net.ssl.* 属性,因为无论如何您都在使用默认值。)
Alternatively, if you have control over the server you're connecting to and its certificate, you can create a certificate of it that matches the naming rules above (CN should be sufficient, although subject alternative name is an improvement). If a self-signed certificate is good enough for what you name, make sure its common name (CN) is the host name you're trying to talk to (no the full URL, just the hostname).
或者,如果您可以控制要连接的服务器及其证书,则可以创建一个与上述命名规则匹配的证书(CN 应该足够了,尽管主题备用名称是一种改进)。如果自签名证书足以满足您的命名要求,请确保其公用名 (CN) 是您尝试与之通信的主机名(没有完整的 URL,只有主机名)。
回答by Zaur_M
I've found a good resolution here: http://www.mkyong.com/webservices/jax-ws/java-security-cert-certificateexception-no-name-matching-localhost-found/
我在这里找到了一个很好的解决方案:http: //www.mkyong.com/webservices/jax-ws/java-security-cert-certificateexception-no-name-matching-localhost-found/
But my problem was a little bit different and solved it differently.
但我的问题有点不同,解决方法也不同。
The web service was on remote host. For example: https://some.remote.host/MyWebService?wsdl
Web 服务位于远程主机上。例如:https: //some.remote.host/MyWebService?wsdl
But it was available only by IP for any clients, but certificate was created for domain: some.remote.host (CN=some.remote.host). And this domain can't be resolved by IP because it is not presented in DNS).
但它只能通过 IP 用于任何客户端,但证书是为域创建的:some.remote.host (CN=some.remote.host)。并且此域无法通过 IP 解析,因为它未出现在 DNS 中)。
So the same problem appeared: if I use IP to connect to web service by ssl, it can't be reached becase certificate CN=some.remote.host and it is not equal to host name I've specified (i.e. host IP).
所以出现了同样的问题:如果我使用 IP 通过 ssl 连接到 Web 服务,则无法访问,因为证书 CN=some.remote.host 并且它不等于我指定的主机名(即主机 IP) .
I've resolved it by matching this hostname with IP in /etc/hosts file. The problem was fixed.
我已经通过将此主机名与 /etc/hosts 文件中的 IP 匹配来解决它。问题已解决。
But in case when the Web Service is hosted on localhost app server, it think, it should be solved like mkyong described in his article.
但是如果Web Service托管在localhost应用程序服务器上,它认为应该像mkyong在他的文章中描述的那样解决。
回答by user2181029
The server name should be same as the first/last name which you give while create a certificate
服务器名称应与您在创建证书时提供的名字/姓氏相同
回答by jaguililla
In Java 8 you can skip server name checking with the following code:
在 Java 8 中,您可以使用以下代码跳过服务器名称检查:
HttpsURLConnection.setDefaultHostnameVerifier ((hostname, session) -> true);
However this should be used only in development!
然而,这应该只在开发中使用!
回答by Cassio Seffrin
I created a method fixUntrustCertificate(), so when I am dealing with a domain that is not in trusted CAs you can invoke the method before the request. This code will gonna work after java1.4. This method applies for all hosts:
我创建了一个方法 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);
}
回答by Senchan Sue
If you're looking for a Kafka error, this might because the upgrade of Kafka's version from 1.x to 2.x.
如果您正在寻找 Kafka 错误,这可能是因为 Kafka 的版本从 1.x 升级到 2.x。
javax.net.ssl.SSLHandshakeException: General SSLEngine problem ... javax.net.ssl.SSLHandshakeException: General SSLEngine problem ... java.security.cert.CertificateException: No name matching *** found
javax.net.ssl.SSLHandshakeException: 一般 SSLEngine 问题 ... javax.net.ssl.SSLHandshakeException: 一般 SSLEngine 问题 ... java.security.cert.CertificateException: 找不到匹配的名称 ***
or
或者
[Producer clientId=producer-1] Connection to node -2 failed authentication due to: SSL handshake failed
[Producer clientId=producer-1] 连接到节点 -2 的身份验证失败,原因是:SSL 握手失败
The default value for ssl.endpoint.identification.algorithm was changed to https, which performs hostname verification (man-in-the-middle attacks are possible otherwise). Set ssl.endpoint.identification.algorithm to an empty string to restore the previous behaviour. Apache Kafka Notable changes in 2.0.0
ssl.endpoint.identification.algorithm 的默认值已更改为 https,它执行主机名验证(否则可能进行中间人攻击)。将 ssl.endpoint.identification.algorithm 设置为空字符串以恢复之前的行为。Apache Kafka 2.0.0 中的显着变化
Solution: SslConfigs.SSL_ENDPOINT_IDENTIFICATION_ALGORITHM_CONFIG, ""
解决方案:SslConfigs.SSL_ENDPOINT_IDENTIFICATION_ALGORITHM_CONFIG,""
回答by jumping_monkey
In case, it helps someone:
万一,它可以帮助某人:
Use case: i am using a self-signed certificate for my development on localhost.
用例:我在本地主机上使用自签名证书进行开发。
Error:Caused by: java.security.cert.CertificateException: No name matching localhost found
错误:引起:java.security.cert.CertificateException:找不到与本地主机匹配的名称
Solution:When you generate your self-signed certicate, make sure you answer this question like that(See Bruno's answer for the why):
解决方案:当您生成自签名证书时,请确保您像这样回答这个问题(有关原因,请参阅布鲁诺的回答):
What is your first and last name?
[Unknown]: localhost
As a bonus, here are my steps:
1. Generate self-signed certificate:
作为奖励,我的步骤如下:
1. 生成自签名证书:
keytool -genkeypair -alias netty -storetype PKCS12 -keyalg RSA -keysize 2048 -keystore keystore.p12 -validity 4000
Enter keystore password: ***
Re-enter new password: ***
What is your first and last name?
[Unknown]: localhost
...
2. Copy the certificate in src/main/resources(if necessary)
2.复制src/main/resources中的证书(如有需要)
3. Update the cacerts
keytool -v -importkeystore -srckeystore keystore.p12 -srcstoretype pkcs12 -destkeystore "%JAVA_HOME%\jre\lib\security\cacerts" -deststoretype jks
3.更新cacerts
keytool -v -importkeystore -srckeystore keystore.p12 -srcstoretype pkcs12 -destkeystore "%JAVA_HOME%\jre\lib\security\cacerts" -deststoretype jks
4. Update your config(in my case application.properties):
4. 更新你的配置(在我的例子中是 application.properties):
server.port=8443
server.ssl.key-store=classpath:keystore.p12
server.ssl.key-store-password=jumping_monkey
server.ssl.key-store-type=pkcs12
server.ssl.key-alias=netty
Cheers
干杯