18

我有两个域:foo.netbar.com. 它们都有 SSL 证书,并且在所有桌面和移动浏览器中都能正常工作。它们托管在使用 nginx 配置的同一台服务器上。

但是,当我从本机 android 应用程序中向域发出请求时,它以某种方式从错误的域中获取证书!这会导致 IO 异常:

request = new HttpPost("https://foo.net/api/v1/baz");
request.setHeader("Authorization", "user:pass");
response = httpClient.execute(request);

...

javax.net.ssl.SSLException: hostname in certificate didn't match: <foo.net> != <bar.com> OR <bar.com> OR <www.bar.com>

bar.com当所有其他措施似乎表明服务器配置正确时,什么会导致 android/java 尝试使用证书?nginx 访问或错误日志中没有出现任何内容。我的android项目中没有提到bar.com任何地方。

编辑:我不知道为什么,但似乎服务器正在使用bar.com服务器 IP的证书https://198.245.xx.xxx

4

3 回答 3

29

The most likely cause for this problem is that the server uses Server Name Indication to choose which certificate to send. If the client doesn't support SNI, the server cannot choose which certificate to send during the SSL/TLS handshake (before any HTTP traffic is sent). SNI is required when you want to use multiple certificates on the same IP address and port, but not all clients support it (notoriously, IE on any version of Windows XP, and a number of mobile browsers).

You're also visibly using the Apache HTTP Client library (not HttpsURLConnection, for which there can be SNI support with some Android versions. Support for SNI in the Apache HTTP Client library is quite recent, and certainly hasn't made it into the Android stack.

You may find the workaround described in this article useful (although it seems only to work for Android 4.2+).

Another two options would be:

  • to use a distinct IP address for each host (so as not to need SNI), if you're in control of server, or
  • to use another HTTP Client library (e.g. HttpsURLConnection).
于 2014-02-22T16:58:40.623 回答
4

Apache 的解决方案,更像是一个技巧:SSL 证书是根据 /etc/apache2/sites-enabled 中的虚拟主机名加载的。因此,为了欺骗检查,请确保首先加载有问题的证书(请记住,虚拟主机是按名称加载的)。

于 2017-02-21T11:33:19.490 回答
0

看起来 foo.net 的证书配置错误,并且使用与 bar.com 相同的主机名

尝试运行一个在线证书验证工具,例如foo.net 上的https://www.digicert.com/help/,以确保安全。

我认为您需要使用正确的主机名重新生成 foo.net 的证书,或者重新配置 ngix 以确保 nginx 为正确的主机提供正确的证书。

于 2014-02-22T16:19:43.950 回答