我有两个域:foo.net
和bar.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>
当其他所有措施似乎表明服务器配置正确时,会导致android / java尝试使用bar.com
中的证书? nginx访问或错误日志中没有任何内容。我的android项目中没有提到bar.com
。
编辑:我不确定原因,但似乎服务器正在使用bar.com
证书作为服务器IP https://198.245.xx.xxx
答案 0 :(得分:27)
此问题的最可能原因是服务器使用Server Name Indication来选择要发送的证书。如果客户端不支持SNI,则服务器无法选择在SSL / TLS握手期间(在发送任何HTTP流量之前)要发送的证书。当您想在同一个IP地址和端口上使用多个证书时,需要SNI,但并非所有客户端都支持它(众所周知,任何版本的Windows XP上的IE,以及许多移动浏览器)。
你也明显地使用Apache HTTP Client库(而不是HttpsURLConnection
,there can be SNI support with some Android versions。
支持Apache HTTP客户端库is quite recent中的SNI,当然还没有进入Android堆栈。
您可能会发现the workaround described in this article很有用(虽然它似乎只适用于Android 4.2 +)。
另外两个选项是:
HttpsURLConnection
)。答案 1 :(得分:2)
Apache的解决方案,更像是一个技巧: 根据/ etc / apache2 / sites-enabled中的vhost名称加载SSL证书。因此,要检查该检查,请确保首先加载有问题的证书(请记住,vhosts是按名称加载的)。
答案 2 :(得分:0)
看起来foo.net的证书配置错误,并使用与bar.com相同的主机名
尝试运行在线证书验证工具,例如foo.net上的https://www.digicert.com/help/,以确定。
我认为您需要使用正确的主机名重新生成foo.net证书,或者重新配置ngix以确保nginx为正确的主机提供正确的证书。