2011-06-02 53 views
0

我正在開發一個使用REST Web服務的Android應用程序。該Web服務位於HTTPS中。我無法提供Web服務的詳細信息,因爲它是保密的。我也跟着在下面的鏈接中提到的步驟:從Android連接到REST web服務拋出javax.net.ssl.SSLException:不可信的服務器證書

http://blog.antoine.li/index.php/2010/10/android-trusting-ssl-certificates/

應用程序工作正常,到目前爲止,並能下載網站服務的內容。突然最後一週,它無法連接並拋出「javax.net.ssl.SSLException:不受信任的服務器證書」。我按照下面提到的步驟設置:

第1步:我使用GeoTrust提供的根證書在我的應用程序中啓用安全通信。如此從地理信任站點收集根證書「GeoTrust_Global_CA.cer」:http://www.geotrust.com/resources/root-certificates/index.html

它是Base64編碼的X.509格式。

步驟2:下載BouncyCastle提供程序並使用此創建的密鑰存儲區。我使用命令行中的java 6 keytool運行以下命令以生成密鑰存儲:

keytool -importcert -v -trustcacerts -file「G:\ workspace \ TestHttps \ GeoTrustglobal.cer」-alias IntermediateCA -keystore「G:\ workspace \ TestHttps \ res \ raw \ mykeystore.bks「-provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath」G:\ workspace \ TestHttps \ SigningProcess \ bcprov-jdk16-146.jar「-storetype BKS -storepass mysecret

成功後,它創建myKeyStore.bks,並將其複製到我的應用程序的/ res/raw文件夾中。

密鑰工具-importcert -v -trustcacerts -file:

然後通過運行下面的命令驗證這個密鑰存儲 「G:\工作空間\ TestHttps \ GeoTrustglobal.cer」 -alias IntermediateCA -keystore「G:\工作區\ TestHttps \ res \ raw \ mykeystore.bks「-provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath」G:\ workspace \ TestHttps \ SigningProcess \ bcprov-jdk16-146.jar「-storetype BKS -storepass mysecret

它返回1結果與中間證書如下:

中級CA,22.10.2010,trustedCertEntry,Th umbprint(MD5):98:0F:C3:F8:39:F7:D8:05:07:02:0D:E3:14:5B:29:43

步驟3:

現在我寫是從DefaultHttpClient

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.mykeystore); 
      try { 
       // Initialize the keystore with the provided trusted certificates 
       // Also provide the password of the keystore 
       trusted.load(in, "mysecret".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以下代碼:

package com.test.https; 

import java.io.IOException; 
import java.net.UnknownHostException; 

import org.apache.http.HttpEntity; 
import org.apache.http.HttpResponse; 
import org.apache.http.ParseException; 
import org.apache.http.client.ClientProtocolException; 
import org.apache.http.client.methods.HttpGet; 
import org.apache.http.impl.client.DefaultHttpClient; 
import org.apache.http.util.EntityUtils; 

import android.app.Activity; 
import android.os.Bundle; 

public class TestHttps extends Activity { 
    /** Called when the activity is first created. */ 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 

     try { 
      startConnect(); 
     } catch (UnknownHostException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
    } 

    public void startConnect() throws UnknownHostException{ 
     DefaultHttpClient client = new MyHttpClient(getApplicationContext()); 
     HttpGet get = new HttpGet("https://ssltest15.bbtest.net/"); 
     // Execute the GET call and obtain the response 
     HttpResponse getResponse = null; 


     try { 
      getResponse = client.execute(get); 
     } catch (ClientProtocolException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch(UnknownHostException uhe){ 
      uhe.printStackTrace(); 
      throw new UnknownHostException();   
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 

     String response = null; 
     if(getResponse != null){ 
      HttpEntity responseEntity = getResponse.getEntity(); 
      try { 
       response = EntityUtils.toString(responseEntity); 
      } catch (ParseException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } catch (IOException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 
     } 
    } 
} 

當我執行該代碼時,它引發以下情況除外:

java.security.cert.CertPathValidatorException:找不到CertPath的TrustAnchor。

javax.net.ssl。異常SSLException:不受信任的服務器證書


所以,我想同樣的應用程序連接到各種其他網絡服務,包括一個由GeoTrust的(https://ssltest15.bbtest.net/)提供。所有拋出相同的例外。我對這個問題的猜測是,

  1. 正在提供REST Web服務的Web服務器,可能就在自己身邊的一些變化,導致此問題

  2. 我使用的地理信託cerificate已過期

  3. 步驟我跟着有一些問題

與上面的代碼相同的應用程序工作正常之前我們1 ek,現在突然失敗意味着,服務器端發生了一些變化,導致此問題。我不清楚確切的問題。

如果有人能幫助我理解這個問題,非常感謝。提前致謝。

+0

嗨。你有沒有辦法解決?我也面臨同樣的問題 – 2011-07-17 05:04:31

+1

看起來在服務器端存在一些問題。我們正在努力。 – Vignesh 2011-07-20 18:25:54

回答

0

看起來好像你沒有正確填充你的信任存儲。我知道你不能討論你的網絡服務的細節,但你的服務的證書是從哪個CA簽署的?您需要將那條鏈放在您的客戶端應用程序的信任密鑰庫中。例如,如果您的Web服務簽署了中間的GeoTrust CA,您應該將中間的GeoTrust CA的證書以及根GeoTrust CA的證書放入您的商店。如果您仍然遇到錯誤,請將Web服務的證書也放入您的客戶端信任庫中。

查看keytool -list輸出,您的信任存儲區中只有一個條目。