得到 'IOException: hostname was not verified',尽管给定的主机名(IP 地址)与通用名称匹配

Got 'IOException: hostname was not verified', although given hostname (IP address) matches common name

我怎么可能在成功插入我的证书后得到一个 IOException: hostname was not verified,并将它用作 OKHttp 的 SSLFactory 实例的一部分?我知道这是自签名证书的常见问题,但前提是服务器上的名称与证书上的名称不匹配。在我的例子中,异常消息向我显示了地址,然后是 CN,它们完全匹配。

我通过提供超级​​宽松的主机验证程序暂时解决了这个问题:

this.client.setHostnameVerifier(new HostnameVerifier() {
    @Override
    public boolean verify(String hostname, SSLSession session) {
        //TODO: Make this more restrictive
        return true;
    }
});

但还是感觉怪怪的。你能告诉我是什么导致了这个问题吗?或者,至少,您认为什么是限制性更强的处理程序?我猜,一个尝试从会话中提取主机名,并与 hostname 参数进行比较的人。

更新: 根据要求,这是堆栈跟踪。出于隐私原因,我不能透露任何数据,但请记住主机名 IP 和 CN 匹配 1:1.

java.io.IOException: Hostname xxx.xxx.xxx.xxx not verified:
certificate: sha1/xxxxxxxxxxxxxxxxxxxxxxxxx=
DN: xxx.xxx.xxx.xxx.xxx.xxx.xxx=#xxxxxxxxxxxxxxxxxxxxxxxxxxxxx,CN=xxx.xxx.xxx.xxx,OU=xxxxxx,O=xxxxxx,L=xxxxxx,ST=xxxxxx,C=xx
subjectAltNames: []
at com.squareup.okhttp.Connection.upgradeToTls(Connection.java:260)
at com.squareup.okhttp.Connection.connect(Connection.java:158)
at com.squareup.okhttp.Connection.connectAndSetOwner(Connection.java:174)
at com.squareup.okhttp.OkHttpClient.connectAndSetOwner(OkHttpClient.java:120)
at com.squareup.okhttp.internal.http.RouteSelector.next(RouteSelector.java:131)
at com.squareup.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:312)
at com.squareup.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:235)
at com.squareup.okhttp.Call.getResponse(Call.java:262)
at com.squareup.okhttp.Call$ApplicationInterceptorChain.proceed(Call.java:219)
at com.squareup.okhttp.Call.getResponseWithInterceptorChain(Call.java:192)
at com.squareup.okhttp.Call.execute(Call.java:79)

Hostname xxx.xxx.xxx.xxx not verified

您似乎正在连接到一个 IP 地址。 IP 的匹配行为因实现而异,但为 RFC2818 (https) 定义的检查要求 IP 地址位于主题备用名称部分 (RFC2818, page 4):

In some cases, the URI is specified as an IP address rather than a hostname. In this case, the iPAddress subjectAltName must be present in the certificate and must exactly match the IP in the URI.

实际行为因实现而异。有些接受 IP 作为 CN,有些则不接受。一些实施正确的行为要求 IP 作为 iPAddress 类型,而另一些则期望它作为 dNSName 类型。所以你最好把它写成 CN,另外在主题替代名称部分写成 iPAdress 和 dNSName :(