Java SSLHandshakeException:证书中的主机名不匹配
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19292473/
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
SSLHandshakeException: hostname in certificate didn't match
提问by EvenLisle
I am writing a system that must make a multipart post to a server (a third-party program called ARX that is currently running on localhost during the development) that has a self-signed certificate.
我正在编写一个系统,该系统必须向具有自签名证书的服务器(一个名为 ARX 的第三方程序,目前在开发过程中运行在本地主机上)进行多部分发布。
I tried to find its certificate, but can only find three different jks files; server.jks, servertrust.jksand serverca.jks.
我试图找到它的证书,但只能找到三个不同的jks文件;server.jks,servertrust.jks和serverca.jks。
I have tried to use the System.setProperty("javax.net.ssl.trustStore", "Program Files\\<path>\\jksfile")
with each of the jks files. However; when I do, I get the following error:
hostname in certificate didn't match: < localhost> != <9200416 arx sa cert>.
我尝试将System.setProperty("javax.net.ssl.trustStore", "Program Files\\<path>\\jksfile")
与每个 jks 文件一起使用。然而; 当我这样做时,我收到以下错误:
证书中的主机名不匹配:< localhost> != <9200416 arx sa cert>。
I have browsed plenty of similar questions here on stackoverflow to try and get an idea on how to fix this, but I have not been able to resolve my problem.
我在 stackoverflow 上浏览了很多类似的问题,试图了解如何解决这个问题,但我一直无法解决我的问题。
Any suggestions? All help is very much appreciated.
有什么建议?非常感谢所有帮助。
采纳答案by Bruno
The certificate itself seems trusted, so your javax.net.ssl.trustStore
setting worked, but the host name doesn't match.
证书本身似乎受信任,因此您的javax.net.ssl.trustStore
设置有效,但主机名不匹配。
Host name matching is done according to how the client identifies the host it's trying to access. If it's trying to access https://localhost/
, then the certificate must be valid for localhost
. If it's trying to access https://something-else.example
, then the certificate must be valid for something-else.example
, even if localhost
and something-else.example
are one and the same machine.
主机名匹配是根据客户端如何识别它试图访问的主机来完成的。如果它尝试访问https://localhost/
,则证书必须对 有效localhost
。如果它试图访问https://something-else.example
,则证书必须对 有效something-else.example
,即使localhost
和something-else.example
是同一台机器。
The identifier in the certificate should be in a Subject Alternative Name extension or, failing that, in the Common Name (CN) of the Subject Distinguished Name.
证书中的标识符应位于主体备用名称扩展名中,否则,应位于主体专有名称的通用名称 (CN) 中。
Here, it looks like your certificate only has a CN and that this CN is for "9200416 arx sa cert
".
在这里,您的证书似乎只有一个 CN,而该 CN 是用于“ 9200416 arx sa cert
”的。
In principle, you could address that problem by having that name point to your localhost using your hosts
file on your development machine. However, that name contains spaces, so it's not even a valid host name.
原则上,您可以通过使用hosts
开发机器上的文件将该名称指向本地主机来解决该问题。但是,该名称包含空格,因此它甚至不是有效的主机名。
You get a couple of options:
你有几个选择:
Re-generate the certificate for that application, so that it uses a proper host name (and if required, adapt your
hosts
file). This might just be a mistake when it was set up. Maybe someone just filled in that name with spaces, without realising it would be used like that in the cert (OpenSSL sometimes calls this "Your Name", for example).A bad option would be to change your application to ignore host name validation. This is a bad option because this leaves your code open to MITM attacks. Of course, this barely matters from localhost to localhost, but that's the kind of code that stays in the code. Because it will prevent an error (that would otherwise be an intended error) from happening, it's likely that removing this from production code will be forgotten. Even in places with good development practices, it's easy to miss. That's a bad option (just to stress this point).
A slightly better variant for this would be to have a custom host name verifier that checks the name it finds is the name you know to be in the certificate.
为该应用程序重新生成证书,以便它使用正确的主机名(如果需要,调整您的
hosts
文件)。这可能只是设置时的错误。也许有人只是用空格填充了该名称,而没有意识到它会在证书中像那样使用(例如,OpenSSL 有时称其为“您的姓名”)。一个糟糕的选择是更改您的应用程序以忽略主机名验证。这是一个糟糕的选择,因为这会使您的代码容易受到 MITM 攻击。当然,这从 localhost 到 localhost 几乎不重要,但这就是代码中保留的那种代码。因为它将防止错误(否则将是预期的错误)发生,所以很可能会忘记从生产代码中删除它。即使在具有良好开发实践的地方,也很容易错过。这是一个糟糕的选择(只是为了强调这一点)。
一个稍微好一点的变体是使用自定义主机名验证器来检查它找到的名称是否是您知道在证书中的名称。