【问题标题】:Android SSL - No Peer CertificateAndroid SSL - 无对等证书
【发布时间】:2012-02-07 00:47:41
【问题描述】:

每当此代码运行时,我都会收到“无对等证书”错误。

SSL 证书有效,从 Namecheap (PositiveSSL) 购买。它前面有 CA crt,可以在 Android 浏览器中正常打开。

HTTP 服务器:nginx

代码:

public void postData() {

// Add your data
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);

nameValuePairs.add(new BasicNameValuePair("string", "myfirststring"));

try {

   HttpPost post = new HttpPost(new URI("https://example.com/submit"));
    post.setEntity(new UrlEncodedFormEntity(nameValuePairs));

    KeyStore trusted = KeyStore.getInstance("BKS");
    trusted.load(null, "".toCharArray());
    SSLSocketFactory sslf = new SSLSocketFactory(trusted);
    sslf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

    SchemeRegistry schemeRegistry = new SchemeRegistry();
    schemeRegistry.register(new Scheme ("https", sslf, 443));
    SingleClientConnManager cm = new SingleClientConnManager(post.getParams(),
            schemeRegistry);

    HttpClient client = new DefaultHttpClient(cm, post.getParams());

    // Execute HTTP Post Request
    @SuppressWarnings("unused")
    HttpResponse result = client.execute(post);

} catch (ClientProtocolException e) {
    // TODO Auto-generated catch block
    Log.e(TAG,e.getMessage());
    Log.e(TAG,e.toString());
    e.printStackTrace();
} catch (IOException e) {
    // TODO Auto-generated catch block
    Log.e(TAG,e.getMessage());
    Log.e(TAG,e.toString());
    e.printStackTrace();
} catch (URISyntaxException e) {
        // TODO Auto-generated catch block
    Log.e(TAG,e.getMessage());
    Log.e(TAG,e.toString());
    e.printStackTrace();
    } catch (KeyStoreException e) {
        // TODO Auto-generated catch block
        Log.e(TAG,e.getMessage());
        Log.e(TAG,e.toString());
        e.printStackTrace();
    } catch (NoSuchAlgorithmException e) {
        // TODO Auto-generated catch block
        Log.e(TAG,e.getMessage());
        Log.e(TAG,e.toString());
        e.printStackTrace();
    } catch (CertificateException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
        Log.e(TAG,e.toString());
        Log.e(TAG,e.getMessage());
    } catch (KeyManagementException e) {
        // TODO Auto-generated catch block
        Log.e(TAG,e.getMessage());
        Log.e(TAG,e.toString());
        e.printStackTrace();
    } catch (UnrecoverableKeyException e) {
        // TODO Auto-generated catch block
        Log.e(TAG,e.getMessage());
        Log.e(TAG,e.toString());
        e.printStackTrace();
    }
}

adb logcat

01-10 15:44:34.872: E/myfirstapp(572): No peer certificate
01-10 15:44:34.872: E/myfirstapp(572): javax.net.ssl.SSLPeerUnverifiedException: No peer certificate
01-10 15:44:34.883: W/System.err(572): javax.net.ssl.SSLPeerUnverifiedException: No peer certificate
01-10 15:44:34.883: W/System.err(572):  at org.apache.harmony.xnet.provider.jsse.SSLSessionImpl.getPeerCertificates(SSLSessionImpl.java:137)
01-10 15:44:34.883: W/System.err(572):  at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:93)
01-10 15:44:34.908: W/System.err(572):  at org.apache.http.conn.ssl.SSLSocketFactory.createSocket(SSLSocketFactory.java:381)
01-10 15:44:34.908: W/System.err(572):  at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:165)
01-10 15:44:34.908: W/System.err(572):  at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:164)
01-10 15:44:34.914: W/System.err(572):  at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:119)
01-10 15:44:34.914: W/System.err(572):  at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:360)
01-10 15:44:34.914: W/System.err(572):  at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555)
01-10 15:44:34.914: W/System.err(572):  at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487)
01-10 15:44:34.914: W/System.err(572):  at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:465)
01-10 15:44:34.933: W/System.err(572):  at com.giggsey.myfirstapp.myfirstappIntent.postData(myfirstappIntent.java:126)
01-10 15:44:34.933: W/System.err(572):  at com.giggsey.myfirstapp.myfirstappIntent.onReceive(myfirstappIntent.java:77)
01-10 15:44:34.933: W/System.err(572):  at android.app.ActivityThread.handleReceiver(ActivityThread.java:2118)
01-10 15:44:34.945: W/System.err(572):  at android.app.ActivityThread.access$1500(ActivityThread.java:122)
01-10 15:44:34.945: W/System.err(572):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1196)
01-10 15:44:34.952: W/System.err(572):  at android.os.Handler.dispatchMessage(Handler.java:99)
01-10 15:44:34.952: W/System.err(572):  at android.os.Looper.loop(Looper.java:137)
01-10 15:44:34.962: W/System.err(572):  at android.app.ActivityThread.main(ActivityThread.java:4340)
01-10 15:44:34.962: W/System.err(572):  at java.lang.reflect.Method.invokeNative(Native Method)
01-10 15:44:34.962: W/System.err(572):  at java.lang.reflect.Method.invoke(Method.java:511)
01-10 15:44:34.972: W/System.err(572):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
01-10 15:44:34.972: W/System.err(572):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
01-10 15:44:34.981: W/System.err(572):  at dalvik.system.NativeStart.main(Native Method)

【问题讨论】:

  • 既然证书是有效的,可以不用自己的SchemeRegistry试试,只依赖默认的android吗?
  • 使用此页面测试证书。我很确定您缺少一些中间证书。 digicert.com/help/index.htm 这应该让您知道这是否是与服务器相关的问题。我认为是。
  • @blindstuff 该页面的所有刻度。
  • 我曾经遇到过这个问题,我得到了所有的滴答声,但是页面有一个警告,上面写着“服务器没有发送所有必需的中间证书。较新的浏览器不会抱怨,但是一些移动设备将发出警告,因为此服务器需要在 SSL 握手期间再发送一个中间证书。"
  • @kenota 就是这样。如果您想提交答案,我会将其标记为解决方案。

标签: android ssl


【解决方案1】:

尽管这个问题有一个公认的答案,但我认为值得回答,因为我在运行 2.3.3 的旧 Android 设备上遇到了同样的错误:

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 也无法正常使用证书。

【讨论】:

  • 感谢您的回答。我遇到了证书排序问题,这让我发疯了——显然有些版本的 android 接受的证书顺序错误,有些则不接受。
  • 对我来说也是如此,rapidssl 颁发的证书是向后的,所有浏览器都可以工作,但我的应用程序失败了。当我重新订购证书时,一切正常。非常感谢!
  • 赞成。我尝试了许多不同的 keytool 和 bouncycastle 受信任密钥库的方法,但最后,Android 2.3 根本不喜欢在我的服务器的 ssl 链中没有中间证书。 Android Jellybean、Firefox、IE 或 Chrome 都没有抱怨——只有 Android 2.3 DefaultHTTPClient。添加 gd_intermediate.crt 后,我​​的 GB 应用程序通过 SSL 运行。详情见这里:informationideas.com/news/2011/11/29/…
【解决方案2】:

如果不是服务器问题,在我看到的大多数情况下,这与缺少中间证书或证书安装错误有关。

尝试像这样使用方案注册表:

SchemeRegistry schReg = new SchemeRegistry();
schReg.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
schReg.register(new Scheme("https",SSLSocketFactory.getSocketFactory(), 443));
SingleClientConnManager conMgr = new SingleClientConnManager(params,post.getParams());

【讨论】:

  • 我使用了mClient = new DefaultHttpClient(); mClient.getConnectionManager().getSchemeRegistry().register(new Scheme("SSLSocketFactory", SSLSocketFactory.getSocketFactory(), 443));,它成功了。谢谢!
  • @shkschneider,你是我的英雄!
  • @shkschneider ...我也用我的HttpClient尝试了这条线,但它给了我同样的错误“没有对等证书”......我正在发送带有https请求的JSON参数......请帮助我
【解决方案3】:

检查您的系统时间。如果时间不是当前时间可能会导致此错误。

【讨论】:

  • 这可以是评论。
【解决方案4】:

我现在实际上正在尝试自己进行诊断,似乎可能导致此问题的一件事是服务器已关闭或连接超时。

【讨论】:

    【解决方案5】:

    我删除了所有 Scheme Registry 人员,“No peer Certification 错误”得到解决。

    即。

    我从我的代码中删除了此代码

    SchemeRegistry schReg = new SchemeRegistry();
    schReg.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
    schReg.register(new Scheme("https",SSLSocketFactory.getSocketFactory(), 443));
    SingleClientConnManager conMgr = new SingleClientConnManager(params,post.getParams());
    

    也许你可以尝试从你的删除那些。

    【讨论】:

      【解决方案6】:

      我尝试通过添加“接受所有证书”规则从 android 代码中解决此问题。但是android方面的所有努力都是徒劳的。 最后在注册商条目中创建一个 CNAME 以确保所有请求都转到相同的 IP 地址解决了问题

      【讨论】:

        【解决方案7】:

        确保您使用的是HttpsURLConnection 而不是HttpURLConnection

        【讨论】:

          【解决方案8】:

          我最近刚刚解决了这个问题。 问题不在于连锁顺序,但我以前也遇到过。

          问题是服务器只接受 TLS1.2 套接字连接。 android 19 及更低的默认套接字连接是 TLS1 SSLSocket Docs

          Enable TLS 1.2 in Android 4.4 的帮助下,我得以完成这项工作。问题描述对我有用。但请确保您的应用程序中确实有答案代码

          【讨论】:

            【解决方案9】:

            因为证书是有效的,所以你不应该使用自定义的 SchemeRegistry,你应该只依赖默认的 android 证书验证机制。

            【讨论】:

            • 您能详细说明一下吗?我似乎无法弄清楚如何使用这个默认机制。
            • 您能否为那些不知道如何为这种默认机制编写代码的人详细说明这一点?
            • 完美。谢谢。 SO有一个字符限制,答案不会接受完美。 #悲伤
            • 拒绝投票,因为答案没有提供有关创建或获取默认 SchemeRegistry 的信息
            • 用好的输入详细说明你的答案,这只是指示性答案。
            猜你喜欢
            • 2018-07-20
            • 1970-01-01
            • 2015-11-21
            • 1970-01-01
            • 1970-01-01
            • 2013-05-19
            • 1970-01-01
            • 1970-01-01
            • 2011-02-26
            相关资源
            最近更新 更多