【问题标题】:Android SSL No peer certificateAndroid SSL 无对等证书
【发布时间】:2013-04-21 11:16:49
【问题描述】:

我有一个例外:没有对等证书

当我询问谷歌时,我得到了解决方案,我信任所有证书。但是这个问题的答案是,它是不安全的。

所以我给班级打电话:

HostnameVerifier hostnameVerifier = org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER;
           HttpClient client = new DefaultHttpClient();

           SchemeRegistry registry = new SchemeRegistry();
           SSLSocketFactory socketFactory = SSLSocketFactory.getSocketFactory();
           socketFactory.setHostnameVerifier((X509HostnameVerifier) hostnameVerifier);
           registry.register(new Scheme("https", socketFactory, 443));
           SingleClientConnManager mgr = new SingleClientConnManager(client.getParams(), registry);
           DefaultHttpClient httpClient = new DefaultHttpClient(mgr, client.getParams());

           HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier);
           Log.v("URL:", Url[0]);
           HttpPost post = new HttpPost(Url[0]);  
           post.addHeader("Username", Url[1]);
           post.addHeader("Passwort", Url[2]);
           HttpResponse getResponse = httpClient.execute(post); //Wirft Exception
           HttpEntity responseEntity = getResponse.getEntity();
           UserID = Integer.parseInt(responseEntity.getContent().toString());

这是我的课:

class MyHttpClient extends DefaultHttpClient {

final Context context;

public MyHttpClient(Context context) {
    this.context = context;
}

@Override
protected ClientConnectionManager createClientConnectionManager() {
    SchemeRegistry registry = new SchemeRegistry();
    registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
    // Register for port 443 our SSLSocketFactory with our keystore
    // to the ConnectionManager
    registry.register(new Scheme("https", (SocketFactory) newSslSocketFactory(), 443));
    return new SingleClientConnManager(getParams(), registry);
}

private SSLSocketFactory newSslSocketFactory() {
    try {
        // Get an instance of the Bouncy Castle KeyStore format
        KeyStore trusted = KeyStore.getInstance("BKS");
        // Get the raw resource, which contains the keystore with
        // your trusted certificates (root and any intermediate certs)
        InputStream in = context.getResources().openRawResource(R.raw.mykey);
        try {
            // Initialize the keystore with the provided trusted certificates
            // Also provide the password of the keystore
            trusted.load(in, "PASSWORT".toCharArray());
        } finally {
            in.close();
        }
        // Pass the keystore to the SSLSocketFactory. The factory is responsible
        // for the verification of the server certificate.
        SSLSocketFactory sf = new SSLSocketFactory(trusted);
        // Hostname verification from certificate
        // [url=http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html#d4e506]Chapter2.Connection management[/url]
        sf.setHostnameVerifier(SSLSocketFactory.STRICT_HOSTNAME_VERIFIER);
        return sf;
    } catch (Exception e) {
        throw new AssertionError(e);
    }
}

}

【问题讨论】:

    标签: android ssl certificate


    【解决方案1】:

    我发现 SSLPeerUnverifiedException 的另一个可能原因:没有对等证书

    如果您的模拟器运行的日期早于证书的创建日期,您可能会遇到此异常。

    我的证书是在 7 月 10 日验证的,但模拟器的当前日期是 5 月 7 日。

    我不知道为什么我的模拟器将日期设置为 5 月 7 日,因为它应该从网络获取时间,但这是另一个问题。

    只是想我应该分享一下,以防它帮助其他人避免浪费几天的时间。

    【讨论】:

    • 我在这上面浪费了两个小时。非常感谢!
    • 我遇到了类似的问题,与实际月份相比,平板电脑有 +1 个月的时间。我也有同样的例外。配置正确的日期修复它!谢谢
    【解决方案2】:

    盲目相信所有证书听起来是个非常糟糕的主意。你真的应该试着找出这个问题的原因。我在运行 2.3.3 的旧 Android 设备上遇到了同样的错误(新的 Android 版本运行没有任何问题,iOS 设备也是如此):

    javax.net.ssl.SSLPeerUnverifiedException: No peer certificate
    

    在阅读了几个关于 SO 的不同相关问题后,我得出的结论是,这可能有两个(也许更多?)原因:

    在我的情况下,证书的顺序不正确。例如,我发布了来自this question 的证书订单以及来自用户bdc 的富有洞察力的回答。您可以通过从终端执行以下操作来获取证书排序:

    openssl s_client -connect eu.battle.net:443
    

    (显然将 eu.battle.net 替换为您自己的服务器)。以 eu.battle.net 为例,当时的顺序是:

    Certificate chain
     0 s:/C=US/ST=California/L=Irvine/O=Blizzard Entertainment, Inc./CN=*.battle.net
       i:/C=US/O=Thawte, Inc./CN=Thawte SSL CA
     1 s:/C=US/O=thawte, Inc./OU=Certification Services Division/OU=(c) 2006 thawte, Inc. - For authorized use only/CN=thawte Primary Root CA
       i:/C=ZA/ST=Western Cape/L=Cape Town/O=Thawte Consulting cc/OU=Certification Services Division/CN=Thawte Premium Server CA/emailAddress=premium-server@thawte.com
     2 s:/C=US/O=Thawte, Inc./CN=Thawte SSL CA
       i:/C=US/O=thawte, Inc./OU=Certification Services Division/OU=(c) 2006 thawte, Inc. - For authorized use only/CN=thawte Primary Root CA
    

    虽然它应该是:

    Certificate chain
     0 s:/C=US/ST=California/L=Irvine/O=Blizzard Entertainment, Inc./CN=*.battle.net
       i:/C=US/O=Thawte, Inc./CN=Thawte SSL CA
     1 s:/C=US/O=Thawte, Inc./CN=Thawte SSL CA
       i:/C=US/O=thawte, Inc./OU=Certification Services Division/OU=(c) 2006 thawte, Inc. - For authorized use only/CN=thawte Primary Root CA
     2 s:/C=US/O=thawte, Inc./OU=Certification Services Division/OU=(c) 2006 thawte, Inc. - For authorized use only/CN=thawte Primary Root CA
       i:/C=ZA/ST=Western Cape/L=Cape Town/O=Thawte Consulting cc/OU=Certification Services Division/CN=Thawte Premium Server CA/emailAddress=premium-server@thawte.com
    

    规则是证书“n”在链中的颁发者应该匹配证书“n+1”的主题。

    一旦我发现问题,更改服务器上的证书顺序是微不足道的,事情立即开始在 Android 2.3.3 设备上运行。我想旧的 Android 版本对证书顺序有点讨厌是件好事,但这也是一场噩梦,因为新的 Android 版本会自动重新排序证书。该死,即使是旧的 iPhone 3GS 也无法正常使用证书。

    【讨论】:

      猜你喜欢
      • 2018-07-20
      • 2012-02-07
      • 2015-11-21
      • 1970-01-01
      • 1970-01-01
      • 2013-05-19
      • 1970-01-01
      • 1970-01-01
      • 2011-02-26
      相关资源
      最近更新 更多