Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ssl/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在服务器证书中使用ip地址作为公共名称在Android中不起作用?_Android_Ssl_Https_Openssl_Okhttp - Fatal编程技术网

在服务器证书中使用ip地址作为公共名称在Android中不起作用?

在服务器证书中使用ip地址作为公共名称在Android中不起作用?,android,ssl,https,openssl,okhttp,Android,Ssl,Https,Openssl,Okhttp,我一直在调查这个问题,发现了一些有趣的东西。 如果我使用一个服务器密钥库来存储服务器证书,该证书的通用名称为real domain,它可以与服务器建立连接,但是如果我使用ip address,而不是通用名称,它就不起作用,而只是在android设备自制的应用程序中(不是android设备中的桌面浏览器或浏览器应用程序)。注意,我使用openssl创建了这两个证书/密钥库。 结果表明,这个异常是主机名未验证 但奇怪的是,桌面或安卓设备的浏览器都很好 经过调查,我发现实际上我们可以构建自己的主

我一直在调查这个问题,发现了一些有趣的东西。 如果我使用一个服务器密钥库来存储服务器证书,该证书的通用名称为real domain,它可以与服务器建立连接,但是如果我使用ip address,而不是通用名称,它就不起作用,而只是在android设备自制的应用程序中(不是android设备中的桌面浏览器或浏览器应用程序)。注意,我使用openssl创建了这两个证书/密钥库。

结果表明,这个异常是主机名未验证

但奇怪的是,桌面或安卓设备的浏览器都很好

经过调查,我发现实际上我们可以构建自己的主机名验证程序,它可以为主机名添加异常,但是android的默认验证程序是如何工作的呢?它必须是一些跳过ip地址作为公共名称并返回false的代码

我检查了okhttp的源代码,找到了这行代码,它引发了异常

但是我找不到自定义主机名验证程序的代码

有人能给我一些提示吗

谢谢~

更新:: 我在android studio中调试之后,在运行时它实际上是OkHostnameVerifier

它检查主机名是否为ip地址,如果是,将检查证书中的所有使用者备选名称,如果找到匹配项,则返回true,反之亦然。

private boolean verifyIpAddress(String ipAddress, X509Certificate certificate) {
    for (String altName : getSubjectAltNames(certificate, ALT_IPA_NAME)) {
      if (ipAddress.equalsIgnoreCase(altName)) {
        return true;
      }
    }
    return false;
  }
如果我使用一个服务器密钥存储库来存储带有CommonName的服务器证书,它是一个真正的域,用于建立与服务器的连接,它可以正常工作,但是如果我使用ip地址来代替CommonName,它就不能正常工作

这就是它的工作原理。IP地址必须作为IP类型的主题备选名称提供。不幸的是,不同的浏览器以不同的方式处理这个问题,并且常常与标准相反。有些人以共同的名义接受IP,其他人则不接受。有些人希望该地址在subject alternative部分中作为DNS条目,而不是IP条目。为了安全起见,您应该使用IP和DNS两种类型的主题替代名称

我们可以构建自己的主机名验证程序,它可以向主机名添加异常


不要这样做。如果忽略主机名,则验证将简化为仅检查信任链,这意味着由受信任CA签名的任何证书都可以用于针对任何其他主机的透明中间人攻击。即使仅对IP地址禁用名称检查,用户通过IP访问站点后仍可以使用任何有效证书

谢谢你的解释!顺便问一下,你知道okhttp在哪里处理这个主机验证器吗?我找不到处理这部分的代码。@Qing:我对OkHttp几乎一无所知,但一个简短的搜索返回的结果是我刚刚用android studio调试了源代码,正确的验证器应该是:com.android.OkHttp.internal.tls.OkHostnameVerifier,因为我可以看到主机名是否是ip地址,它将执行以下检查:for(字符串altName:getSubjectAltNames(证书,ALT_IPA_NAME)){if(ipAddress.equalsIgnoreCase(altName)){return true;}返回false;我想就像你说的检查ip的主题替代名称,如果不是,则返回false!你不应该使用
CN
作为主机名。如果这样做,那么主机名必须同时位于
CN
SAN
中。你应该在
CN
中放置一个友好的名称,因为这会显示给用户。无法避免将主机名(或IP地址)放入
SAN
。有关详细信息,请参阅(包括对各种标准的参考)此外,正在移动IP地址的使用。将来可能会造成问题。例如,您不能将IP地址与一起使用,也不能将其用于。如果存在dNSName类型的subjectAltName扩展名,则必须将其用作标识。否则,(最具体的)必须使用证书的“主题”字段中的“通用名称”字段。虽然使用通用名称是现有做法,但不推荐使用,并鼓励证书颁发机构改用dNSName。[…]在某些情况下,URI被指定为IP地址而不是主机名。在这种情况下,iPAddress subjectAltName必须出现在证书中,并且必须与URI中的IP完全匹配。