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

24

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

我需要从移动 Android 客户端使用我的服务器证书,我找到了关于这个问题的很好的文章 - 在 Android 中使用 Retrofit 和自签名或未知的 SSL 证书。 我按照所有步骤进行了操作,但不幸的是出现了错误(异常)。

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)

您可以看到主机名相同,但错误仍然存在。
请帮我解决这个问题,我将非常感激任何帮助。
谢谢。

伪解决方案

当然,我之前进行了搜索并找到了主机名验证器解决方案
我已经尝试过了,它起作用了。但是使用此解决方法是否可行?我将证书添加到了我的应用程序中以便像先前的示例一样动态读取它,它在这种情况下是否仍然被使用。

使用OkHttp的解决方案只需一行代码。(如果您按照教程中的所有步骤操作)

 okHttpClient.setHostnameVerifier(new NullHostNameVerifier());

但我仍然觉得这不是最好的解决方案,你有任何想法吗?

3个回答

29

有趣的是,如果请求的主机是IP地址,“CN”不用于匹配它;相反,证书中必须存在iPAddress subjectAltName,并且必须与URI中的IP完全匹配。

如果您使用Java的keytool,则可以通过以下方式完成

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

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

对于你的使用情况来说,NullHostNameVerifier也可以。你的客户端只信任一个证书;只要连接使用该证书,你就是安全的;这里主机名并不重要。


不幸的是,这对我没有起作用,即使添加了SAN,我仍然遇到了相同的错误。不得不切换到注册本地主机名。 - Alberto M
对于那些使用Windows PowerShell创建证书的人,可以使用以下命令: New-SelfSignedCertificate -TextExtension @("2.5.29.17={text}IPAddress=10.0.2.2") ............ - Jerry B. no.1 intern

3
自签名证书仅适用于开发。你不能用它上线,因为它没有经过验证,应用程序和浏览器不会信任你,除非有证书授权机构的认可。
所以,这不是你的正式应用的“解决方案”,只能用来测试它是否工作(并且如果你获得有效证书,它将与有效证书一起工作)。因为你允许所有主机名(或者至少限制在几个硬编码的主机名),这两种情况都不好。
你计划在你的正式应用中也使用自签名证书吗?

-1

对于 HttpsURLConnection,您可以使用以下代码:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接