【问题标题】:Java SSLException: hostname in certificate didn't match. Veryfing wrong certificate?Java SSLException:证书中的主机名不匹配。非常错误的证书?
【发布时间】:2014-12-16 00:09:46
【问题描述】:

我正在为 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的问题?

【问题讨论】:

  • 为什么不将所有 :80 请求和 :443 www 请求重定向到单个 443 rapidnote.emendus.ovh 地址,而不是尝试使用单个 SSL 覆盖多个端点?
  • 因为 SSL 验证发生在重定向之前,所以它会失败并在开始时停止。

标签: android apache ssl https


【解决方案1】:

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

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

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

【讨论】:

    【解决方案2】:

    SSL 证书是通过 IP 地址而不是域名来查找的。​​p>

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

    如果您切换条目,www.rapidnote.emendus.ovh 条目将起作用,而另一个则不起作用。

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

    如果您只能使用一个 IP 地址,我建议您研究通配符和通用通信证书。

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

    【讨论】:

    • 我正在使用 SNI 在一个 IP 上拥有多个 CA,每个域名一个,并且它与 webbrowser 完美配合,但就像 Bruno 所说,Android Apache HTTp Client 似乎不支持 SNI。
    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-18
      相关资源
      最近更新 更多