2012-01-10 165 views
12

无论何时运行此代码,我都会收到'无对等证书'错误。Android SSL - 无对等证书

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(); 
    } 
} 

亚行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) 
+1

因为证书是有效的,你可以尝试没有自己SchemeRegistry,仅仅依靠默认的Android? – kenota 2012-01-10 15:56:23

+2

使用此页面测试证书。我很确定你错过了一些中级证书。 https://www.digicert.com/help/index.htm这应该让你知道这是否与服务器相关的问题。我认为这是。 – blindstuff 2012-01-10 15:57:24

+0

@blindstuff该页面上的所有记号。 – giggsey 2012-01-10 15:58:32

回答

20

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

javax.net.ssl.SSLPeerUnverifiedException: No peer certificate 

,所以我读几个不同的相关问题后得出的结论,这可能发生两个(或许更多?)的原因:

  • 不正确的安装中间证书的
  • 证书链顺序有误

在我的情况下,这是一个不正确的证书排序。作为一个例子,我将从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/[email protected] 
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/[email protected] 

的规则是,证书的颁发者“N”链条应符合证书“n + 1”的主题。

一旦我发现问题,更改服务器上的证书订单和立即开始在Android 2.3.3设备上工作的事情是微不足道的。我想早期的Android版本对于证书订单有点讨厌是件好事,但它也是一个噩梦,因为更新的Android版本会自动对证书进行重新排序。地狱,即使是一个旧的iPhone 3GS的失败证书工作。

+0

谢谢你的回答。我有证书订购问题,这让我发疯 - 显然有些版本的android以错误的顺序接受证书,有些则没有。 – 2013-07-05 18:14:00

+0

同样对我来说,rapidssl发布的证书是倒退的,所有浏览器都能正常工作,但是我的应用程序失败了。当我重新排列证书时,一切正常。非常感谢! – mvsjes2 2013-08-19 04:08:29

+0

Upvoted。我尝试了许多不同的keytool和bouncycastle可信密钥存储方法,但最终Android 2.3根本不喜欢在我的服务器的ssl链中没有中间证书。 Android Jellybean,Firefox,IE或Chrome都没有抱怨 - 只有Android 2.3 DefaultHTTPClient。添加gd_intermediate.crt后,我的GB应用程序通过SSL工作。详情请看这里:http://informationideas.com/news/2011/11/29/android-making-https-requests-with-ssl-from-godaddy-no-peer-certificate-error/ – wufoo 2014-01-30 15:07:14

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()); 
+3

我使用了'mClient = new DefaultHttpClient(); mClient.getConnectionManager()。getSchemeRegistry()。register(new Scheme(“SSLSocketFactory”,SSLSocketFactory.getSocketFactory(),443));'它工作。谢谢! – shkschneider 2012-11-05 17:46:15

+0

@shkschneider,你是我的英雄! – sha256 2013-08-24 16:14:02

+2

@shkschneider ...我也想这符合我的HttpClient但它给我同样的错误“没有对等证书” ......我发送JSON PARAMS与HTTPS请求...... 请帮我 – Noman 2013-09-10 10:59:12

-1

因为证书是有效的,你不应该使用自定义SchemeRegistry,你应该仅仅依靠Android默认证书验证机制。

+2

能否请您详细说明这个?我似乎无法弄清楚如何使用这种默认机制。 – 2012-02-01 07:47:36

+3

对于那些不知道如何为这个默认机制编码的人,你能详细说明一下吗? – JPM 2012-06-15 18:14:43

+0

完美。谢谢。 SO有答案的字符限制不会接受完美。 #sad – 2012-11-07 07:50:53

3

white paper可以概括你需要知道让你的SSL在Android上工作的一切。根据我最近的经验,最好的方法是获得Android喜欢的SSL证书。

+1

“最好的方法是获得Android喜欢的SSL证书。”不幸的是,唯一有用的是当你有控制服务器端的豪华时。这很少见。但是,这份白皮书绝对有用。 – 2012-09-12 18:20:02

0

实际上,我想现在这个诊断自己,似乎一两件事,可能会导致此问题是,服务器关闭或连接超时。

0

我删除了所有Scheme Registry工作人员,并解决了“无同行认证错误”。

即。

我删除此代码从我

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()); 

可能是你可以试着删除那些从你的。

0

我试图通过添加“接受所有证书”规则从Android的代码解决这个问题。但是从android方面的所有努力都毫无价值。 最后在注册商条目中做一个CNAME,确保所有请求都转到相同的IP地址修复问题

1

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

+1

这可以是一个评论。 – 2015-08-11 05:10:13

0

确保您使用HttpsURLConnection代替HttpURLConnection