SSL 证书在 android 个应用程序中已过期,但在 pc/mobile 个浏览器中未过期

SSL certificate expired in android app but not in pc/mobile browsers

这是一个奇怪的情况。我在 https 上有一个网站 运行。我在 android 上还有一个应用程序,它利用该网站进行休息 API 通话。到目前为止一切正常。最近我的托管人改变了一些东西,一切都崩溃了。当我从浏览器发出休息请求时,它工作正常。但是,当我使用该应用程序执行此操作时,它不起作用,并且出现此异常:

javax.net.ssl.SSLHandshakeException: com.android.org.bouncycastle.jce.exception.ExtCertPathValidatorException: Could not validate certificate: Certificate expired at Thu Aug 21 06:03:34 EDT 2014 (compared to Sat Aug 22 17:41:59 EDT 2015) at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java

但在 PC 上一切正常,我仔细检查了证书将于 2016 年到期。

所以我更进一步,尝试浏览我的网站,我得到了一些有趣的结果。在 300 个浏览器中,我在几个浏览器中遇到了同样的问题。

http://i.stack.imgur.com/d86tE.png
http://oi60.tinypic.com/30ml1n4.jpg

此外,我现在在安装 SSL 时在我的主机中收到此警告。

"Note: You do not have a dedicated IP address. As a result, web browsers that do not support SNI will probably give false security warnings to your users when they access any of your SSL websites. Microsoft® Internet Explorer™ on Windows XP™ is the most widely used web browser that does not support SNI."

我不是 100% 确定这个警告是否更早出现,但我只是想把各个部分放在一起。

代码没有任何问题,因为我在 phone 上的应用程序已经停止工作,而这些应用程序之前可以正常工作。

Server Name Indication (SNI) 表示客户端(浏览器、应用程序)在 SSL/TLS 握手中发送预期的主机名。这类似于 Host HTTP header 并且可以让具有不同主机名的多个虚拟服务器共享相同的 IP 地址。 如果您的客户端不支持 SNI,服务器将发回一些默认证书或在 SSL/TLS 握手中触发错误。

所有现代浏览器都支持 SNI,但较旧的浏览器或 XP 上的 IE8 等平台不支持 SNI。还有 Android SDK does not support SNI 附带的 Apache HTTP 请求库,这可能是您遇到的问题。

Everything was working fine until now. Recently my hoster changed something and everything is falling apart.

我猜这是不完整更改的结果。看起来使用 SNI 的客户端证书已被更新的版本替换,因为之前的证书已过期。但是站点的默认证书,即用于 non-SNI 客户端的证书,仍然是旧的过期证书。因此,您获得了所有使用 SNI 的客户端的有效证书,但所有无法执行 SNI 的客户端都获得了过期错误。

我 运行 在从我的 android 应用呼叫第三方 API 时遇到同样的问题。 为了解决这个问题,我使用了 javax.net.ssl 包中的 HttpsURLConnection class,它支持 SNI。

执行 API 调用的示例。

import javax.net.ssl.HttpsURLConnection;
import java.net.URL;

public void performApiCall() {
    try {
            URL url = new URL("https://yourdestination.com");
            HttpsURLConnection connection = (HttpsURLConnection)url.openConnection();
            connection.setRequestProperty("content-type", "application/x-www-form-urlencoded");
            connection.setRequestMethod("POST");

            // other stuffs like adding parameters etc. Used android.util.Pair.

            connection.connect();

            // you can read response based on connection.getResponseCode()
    }catch(Exception e){
        e.printStackTrace();
    }
}