Java SSLException:证书中的主机名没有匹配。验证错误的证书?

时间:2014-10-20 21:35:07

标签: android apache ssl https

我正在编写简单的记事本,用于通过互联网与我的服务器同步数据的android。我使用了来自startssl的https和免费证书,一切顺利。后来我用它自己的ssl证书添加了新的虚拟主机,我的应用程序突然停止了对服务器的连接。它抛出:

javax.net.ssl.SSLException: hostname in certificate didn't match: <www.rapidnote.emendus.ovh> != <othersite.emendus.ovh> OR <othersite.emendus.ovh> OR <emendus.ovh>

它尝试从不同的apache虚拟主机验证完全不同的证书。我的用于rapidnote虚拟主机的apache配置是:

<VirtualHost *:80>
  ServerName                rapidnote.emendus.ovh
  ServerAlias               www.rapidnote.emendus.ovh
  Redirect Permanent        /   https://www.rapidnote.emendus.ovh
</VirtualHost>

<VirtualHost *:443>
  ServerName                rapidnote.emendus.ovh
  DocumentRoot              /var/www/rapidnote
  SSLEngine                 on
  SSLCertificateFile        cert_location/rapidnote.emendus.ovh.crt
  SSLCertificateKeyFile     key_location/rapidnote.emendus.ovh.key
  SSLCertificateChainFile   cert_location/sub.class1.server.ca.pem
</VirtualHost>

<VirtualHost *:443>
  ServerName                www.rapidnote.emendus.ovh
  DocumentRoot              /var/www/rapidnote
  SSLEngine                 on
  SSLCertificateFile        cert_location/www.rapidnote.emendus.ovh.crt
  SSLCertificateKeyFile     key_location/www.rapidnote.emendus.ovh.key
  SSLCertificateChainFile   cert_location/sub.class1.server.ca.pem
</VirtualHost>

我的代码如下:

HttpClient   httpClient = new DefaultHttpClient();
HttpPost     httpPost   = new HttpPost("https://www.rapidnote.emendus.ovh/" + paramScriptName);
HttpResponse response   = httpClient.execute(httpPost);

如果我在apache中关闭othersite.emendus.ovh虚拟主机,则SSLException消息显示:

<www.rapidnote.emendus.ovh> != <rapidnote.emendus.ovh> OR <rapidnote.emendus.ovh> OR <emendus.ovh> 

如果我将"https://www.rapidnote.emendus.ovh/"更改为"https://rapidnote.emendus.ovh/",它就会开始工作。我检查了两个(www。和非www)证书,两者中的通用名称都是正确的。 我认为应该验证我在HttpPost构造函数中给他的域证书,而不是我服务器上的其他随机证书......

我使用了一些测试网站来验证我的ssl配置,它表示一切都很好。

android 4.2.2 (API 17)上发生的一切。 我使用min SDK 14target SDK API 20 Android 4.4 (KitKat Wear)

构建了应用

如何告诉他验证为此域名指定的正确证书? 是应用程序或apache网站上的问题吗?

3 个答案:

答案 0 :(得分:5)

您的服务器配置为使用服务器名称指示(SNI)显示不同的证书。

据我所知,与Android捆绑在一起的Apache HTTP Client版本不支持SNI。您可以尝试使用HttpsURLConnection代替HttpClient,这应该支持Android版本中不太旧的SNI。 the answers to this question中有更多详细信息。

请注意,您仍然需要为主机名提供的证书对该主机名有效,即它需要该名称的主题备用名称条目(或者主题DN的CN需要是如果没有DNS SAN,则为该名称。 (如果您有这样的证书,也可以使用通配符。)

答案 1 :(得分:0)

SSL证书由IP地址而非域名查找。

因此,在检查证书时,第一个条目是获胜的条目,在您的情况下是:rapidnote.emendus.ovh

如果您改变了条目,www.rapidnote.emendus.ovh条目将起作用,而不是另一条。

我认为有一种方法可以让www和非www域名在一个证书上工作,但我无法记住确切的过程,抱歉。希望有人会填写这些细节,我们都会学习。我认为有些CA会给你这两个地址,但我又不确定他们是如何制作这个证书的。

如果您只需要使用一个IP地址,我建议您查看通配符和通用通信证书。

如果您可以拥有多个IP地址,请为每个网址分配不同的IP地址。但这确实看起来像生产服务器,因为您直接使用80/433。这个建议不是超级推荐的。我喜欢为我的www和非www网址提供一个IP地址。

答案 2 :(得分:0)

如果代码很大,并且您不想更改连接库,则解决方法是为每个VirtualHost设置不同的端口。这解决了我的问题。