Android 2.3 中的“无对等证书"错误,但 4 中没有 [英] 'No peer certificate' error in Android 2.3 but NOT in 4

查看:20
本文介绍了Android 2.3 中的“无对等证书"错误,但 4 中没有的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在运行 Android 2.3 但不在 4 中的模拟器中获取 "javax.net.ssl.SSLPeerUnverifiedException: No peer certificate error".在 4 中,它运行良好.我正在尝试通过 https 连接到实时服务器.它使用有效的 Thawte 证书,适用于所有浏览器以及 Android 3 和 4.

Getting the "javax.net.ssl.SSLPeerUnverifiedException: No peer certificate error" in an emulator running Android 2.3 but NOT in 4. In 4 it works perfectly. I'm trying to connect to a live server via https. It uses a valid Thawte certificate, works fine in all browsers and Android 3 and 4.

如果有人有代码帮助,请和谢谢.此外,如果有人对安全解决方法有任何建议,我将不胜感激.我还在学习,我已经解决这个问题一个星期了.它必须结束,这样我才能继续工作和学习.呃.

If anyone has code help, PLEASE and thanks. Also, if anyone has any suggestions on a secure workaround, I'd appreciate it. I'm still learning, and I've been on this problem for a week. It has to end, so I can continue working and learning. Urgh.

这是 HttpCLient 代码,由 Antoine Hauck 提供(http://blog.antoine.li/2010/10/22/android-trusting-ssl-certificates/):

Here is HttpCLient code, courtesy Antoine Hauck (http://blog.antoine.li/2010/10/22/android-trusting-ssl-certificates/):

 import java.io.InputStream;
    import java.security.KeyStore;
    import java.security.cert.CertificateException;

    import javax.net.ssl.SSLContext;
    import javax.net.ssl.TrustManager;
    import javax.net.ssl.X509TrustManager;
    import javax.security.cert.X509Certificate;

    import org.apache.http.conn.ClientConnectionManager;
    import org.apache.http.conn.scheme.PlainSocketFactory;
    import org.apache.http.conn.scheme.Scheme;
    import org.apache.http.conn.scheme.SchemeRegistry;
    import org.apache.http.conn.ssl.SSLSocketFactory;
    import org.apache.http.impl.client.DefaultHttpClient;
    import org.apache.http.impl.conn.SingleClientConnManager;

    import android.content.Context;

    public 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", 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.my_cert);
             try {
                 // Initialize the keystore with the provided trusted certificates
                 // Also provide the password of the keystore
                 trusted.load(in, "my_pass".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
            // http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html#d4e506
            sf.setHostnameVerifier(SSLSocketFactory.STRICT_HOSTNAME_VERIFIER);
            return sf;
        } catch (Exception e) {
            throw new AssertionError(e);
        }
    }
}

这是实例化它的代码:

DefaultHttpClient client = new MyHttpClient(getApplicationContext());

           HttpPost post = new HttpPost(server_login_url);
           List <NameValuePair> parameters = new ArrayList <NameValuePair>();
           parameters.add(new BasicNameValuePair("username", user));
           parameters.add(new BasicNameValuePair("password", pass));

            try {
               post.setEntity(new UrlEncodedFormEntity(parameters, HTTP.UTF_8));
            } catch (UnsupportedEncodingException e2) {
                // TODO Auto-generated catch block
                Log.d(DEBUG_TAG, "in  UnsupportedEncodingException - " + e2.getMessage());
                e2.printStackTrace();
            }
                // Execute the GET call and obtain the response
           HttpResponse getResponse = null;

            try {
                getResponse = client.execute(post);
            } catch (ClientProtocolException e) {
                // TODO Auto-generated catch block
                // Toast.makeText(getBaseContext(),message,Toast.LENGTH_LONG).show();
                Log.d(DEBUG_TAG, "in ClientProtocolException - " + e.getMessage());
            } catch (IOException e) {
                // TODO Auto-generated catch block
                // Toast.makeText(getBaseContext(),message,Toast.LENGTH_LONG).show();
                Log.d(DEBUG_TAG, "in  client.execute IOException - " + e.getMessage());
                e.printStackTrace();
            }

错误在 IOException 块中被捕获.这是堆栈:

The error is caught in the IOException block. Here is the stack:

javax.net.ssl.SSLPeerUnverifiedException: No peer certificate
org.apache.harmony.xnet.provider.jsse.SSLSessionImpl.getPeerCertificates(SSLSessionImpl.java:258)
org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:93)
org.apache.http.conn.ssl.SSLSocketFactory.createSocket(SSLSocketFactory.java:381)
org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:164)
org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:164)
org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:119)
org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:359)
org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555)
org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487)
org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:465)
org.ffb.tools.SplashActivity$LoginTask.makeConnection(SplashActivity.java:506)
org.ffb.tools.SplashActivity$LoginTask.doLogin(SplashActivity.java:451)
org.ffb.tools.SplashActivity$LoginTask.doInBackground(SplashActivity.java:439)
org.ffb.tools.SplashActivity$LoginTask.doInBackground(SplashActivity.java:1)
android.os.AsyncTask$2.call(AsyncTask.java:185)
java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:306)
java.util.concurrent.FutureTask.run(FutureTask.java:138)
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581)
java.lang.Thread.run(Thread.java:1019)

这是链式顺序(来自 openssl 命令):

Here is the chain order (from openssl command):

我觉得这个链条看起来不错.

The chain looks good I think.

    i:/C=US/O=Thawte, Inc./OU=Domain Validated SSL/CN=Thawte DV SSL CA
  1 s:/C=US/O=Thawte, Inc./OU=Domain Validated SSL/CN=Thawte DV 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

推荐答案

这个 thread 在我调试类似问题时非常有帮助.

This thread was really helpful when I debugged a similar issue.

总结 Android 2.3 HTTPS/SSL 清单:

Summary Android 2.3 HTTPS/SSL checklist:

  • 如果您的 CA 在 Android 的 2.3 受信任的 CA 列表 -- 而 Thawte 是 -- 无需在应用程序中包含证书.
  • Android 2.3 不支持 服务器名称指示,因此如果您的服务器依赖它SSL 握手,Android 可能无法获得您期望的证书.
  • 您是否在服务器上安装了证书链,并且顺序是否正确?大多数浏览器会处理乱序的证书链,但 Android 2.3 不会.bdc 在我上面提到的线程中的回答描述了如何使用openssl s_client -connect yourserver.com:443"检查 SSL 证书和链的有效性.
  • 当你在底部抽屉里挖掘旧的 2.3 设备时,请确保它的日期和时间在长时间无电后设置正确.
  • If your CA is in Android's 2.3 list of trusted CA's -- and Thawte is -- there's no need to include the certificate in the app.
  • Android 2.3 does not support Server Name Indication so if your server is relying on it for SSL handshaking, Android may not be getting the certificates you're expecting.
  • Do you have certificate chain on the server installed, and is it ordered correctly? Most browsers handle out-of-order certificate chains but Android 2.3 does not. bdc's answer in the thread I mentioned above describes how to check the validity of your SSL certificate and chain with "openssl s_client -connect yourserver.com:443".
  • When digging up that old 2.3 device you have in your bottom drawer, please ensure its date and time are set correctly after being powerless for too long.

这篇关于Android 2.3 中的“无对等证书"错误,但 4 中没有的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆