2012-01-10 205 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