javax.net.ssl.SSLPeerUnverifiedException:主机名未验证:

Posted

技术标签:

【中文标题】javax.net.ssl.SSLPeerUnverifiedException:主机名未验证:【英文标题】:javax.net.ssl.SSLPeerUnverifiedException: Hostname not verified: 【发布时间】:2015-08-25 01:20:52 【问题描述】:

我正在尝试使用带有自签名证书的HTTPS 连接。 我已按照此处提到的创建自签名证书的步骤进行操作 - Creating Self-signed certificate。 即使在浏览器中也一切正常,它只向我显示我的证书由未知 CA 签名的消息。 但是我在证书中的 FQDN(服务器名称不匹配)名称存在问题,因为我在生成证书时设置了错误的名称。 我已经重新生成它,现在没有这样的错误。

我需要使用来自移动 android 客户端的服务器证书,我找到了关于这个问题的精彩文章 - Use Retrofit with a self-signed or unknown SSL certificate in Android。 我已按照所有步骤操作,但不幸的是出现错误(异常)。

javax.net.ssl.SSLPeerUnverifiedException: Hostname 195.xx.xx.xx not verified:
    certificate: sha1/qvH7lFeijE/ZXxNHI0B/M+AU/aA=
    DN: 1.2.840.113549.1.9.1=#160e63726f73704078616b65702e7275,CN=195.xx.xx.xx,OU=Departament of Development,O=CROSP Solutions,L=Chernihiv,ST=Chernihiv,C=UA
    subjectAltNames: []
            at com.squareup.okhttp.internal.http.SocketConnector.connectTls(SocketConnector.java:124)

您可以看到主机名相同,但仍然存在错误。 请帮助处理这个问题,我将不胜感激。 谢谢。

伪解决方案

当然我之前搜索过,发现HostName Verifier Solution。 我已经尝试过了,它有效。但是是否可以使用此解决方法,我将证书添加到我的应用程序中以便像前面的示例中那样动态读取它,在这种情况下是否仍在使用它。

使用 OkHttp 的解决方案是一行。 (如果您遵循教程中的所有步骤)。

 okHttpClient.setHostnameVerifier(new NullHostNameVerifier());

但我仍然觉得这不是最好的解决方案,请大家有什么想法?

【问题讨论】:

【参考方案1】:

有趣的是,如果请求主机是IP,则不用“CN”来匹配它;相反,

https://www.rfc-editor.org/rfc/rfc2818#section-3.1

iPAddress subjectAltName 必须存在于证书中,并且必须与 URI 中的 IP 完全匹配”

如果你使用java的keytool,可以通过

keytool -genkeypair  -ext SAN=IP:195.xx.xx.xx    ........

NullHostNameVerifier 也适合您的用例。您的客户只信任一个证书;只要连接使用该证书,您就是安全的;主机名在这里无关紧要。

【讨论】:

不幸的是,这对我不起作用,即使添加了 SAN,我仍然遇到同样的错误。不得不切换到注册本地主机名 对于那些使用 Windows PowerShell 创建证书的人,其 New-SelfSignedCertificate -TextExtension @("2.5.29.17=textIPAddress=10.0.2.2") ............【参考方案2】:

自签名证书仅适用于开发。你不能使用它,因为你知道它没有经过验证,如果没有 CA 的批准,应用程序和浏览器不会信任你。

因此,这不是您的实时应用程序的“解决方案”,而只是为了测试它是否有效(并且在您获得有效证书时可以使用)。因为您允许所有主机名(或者如果您将其限制为几个,至少是硬编码的主机名)并且两者都是错误的。

您是否也打算在您的实时应用中使用自签名证书?

【讨论】:

【参考方案3】:

对于HttpsURLConnection,您可以使用:

HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
connection.setHostnameVerifier(new AllowAllHostnameVerifier());

【讨论】:

以上是关于javax.net.ssl.SSLPeerUnverifiedException:主机名未验证:的主要内容,如果未能解决你的问题,请参考以下文章