2012-02-03 72 views
1

在我的情況下,當我在模擬器上運行程序 - 它的工作正確。 但是,當我安裝apk到手機 - 有錯誤不可信服務器證書。 問題是什麼?Android Https錯誤不可信服務器證書

有我的AsyncTask的發送響應的服務器代碼:

public abstract class BaseAsyncWorker extends AsyncTask<String, Void, String>{ 
public static final String AS = "BaseAsyncWorker"; 
private String URL; 
private String result; 
final Context context; 

public BaseAsyncWorker(String url,Context context){ 
    this.URL = url; 
    this.context = context; 
} 
//before 
@Override 
protected abstract void onPreExecute(); 

//background 
@Override 
protected String doInBackground(String... objects) { 
    for (String obj : objects) { 
     Log.d(AS,obj.toString()); 
     Log.d(AS,"beginning background"); 
     Logger.appendLog("Start response..."); 
     try{ 


      HostnameVerifier hostnameVerifier = SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER; 

      DefaultHttpClient client = new DefaultHttpClient(); 

      SchemeRegistry registry = new SchemeRegistry(); 
      SSLSocketFactory socketFactory = SSLSocketFactory.getSocketFactory(); 
      socketFactory.setHostnameVerifier((X509HostnameVerifier)hostnameVerifier); 
      registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80)); 
      registry.register(new Scheme("https", socketFactory,443)); 
      SingleClientConnManager mngr = new SingleClientConnManager(client.getParams(), 
                     registry); 
      //trustEveryone(); 
      DefaultHttpClient httpClient = new DefaultHttpClient(mngr,client.getParams()); 

      //MMGHttpClient httpClient = new MMGHttpClient(context); 
      //httpClient.getParams().setParameter(CoreProtocolPNames.USER_AGENT, "MyMobiGift Ltd. Android"); 
      //HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier); 

      HttpPost httpPost = new HttpPost(URL); 

      StringEntity se = new StringEntity(obj); 
      httpPost.setEntity(se); 
      httpPost.setHeader("Accept", "application/json"); 
      httpPost.setHeader("Content-type", "application/json"); 



      HttpResponse response = (HttpResponse)httpClient.execute(httpPost); 
      StatusLine status = response.getStatusLine(); 
      if((status.getStatusCode())==200){ 
       HttpEntity entity = response.getEntity(); 
       if(entity!=null){ 
        InputStream instream = entity.getContent(); 
        result= convertStreamToString(instream); 
        instream.close(); 
        Logger.appendLog("End response with result: "+result); 
       }else{ 
        result=null; 
        Logger.appendLog("End response without result"); 
       } 
      } 
     }catch (ClientProtocolException e) {Logger.appendLog("ClientProtocolException at"+e.getMessage());} 
     catch (IOException e) {Logger.appendLog("IOException at" + e.getMessage());} 

    } 
    return result; 
} 
+0

也許我應該在keytool.bks使用sertiftkat? 如何製作和哪些文件?我有crt和pem文件。 以及爲什麼emulyator在沒有它們的情況下工作? – 2012-02-03 16:38:23

+0

請幫我... – 2012-02-03 16:39:00

+0

有時這種情況發生,如果設備的日期是在20世紀70年代等 – 2012-02-03 16:39:13

回答

1

您可以通過使用addSLLCertificateToHttpRequest()方法來覆蓋Web服務器的證書。在與您的服務器通信之前,請致電addSLLCertificateToHttpRequest()方法。這將避免證書無效並始終返回true。我正在寫這個方法。這對我很有用

/** 
* The server has a SSL certificate. This method add SSL certificate to HTTP 
* Request 
*/ 
public static void addSLLCertificateToHttpRequest() { 
    // Code to use verifier which return true. 
    try { 
     SSLContext sslctx = null; 
     try { 
      sslctx = SSLContext.getInstance("TLS"); 
      sslctx.init(null, new TrustManager[] { new X509TrustManager() { 
       public void checkClientTrusted(X509Certificate[] chain, String authType) 
       { 
       } 

       public void checkServerTrusted(X509Certificate[] chain, String authType) 
       { 
       } 

       public X509Certificate[] getAcceptedIssuers() { 
        return new X509Certificate[] {}; 
       } 
      } }, null); 
     } catch (NoSuchAlgorithmException e) { 
      e.printStackTrace(); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
     HttpsURLConnection.setDefaultSSLSocketFactory(sslctx.getSocketFactory()); 
     HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() { 
      public boolean verify(String hostname, SSLSession session) { 
       return true; 
      } 
     }); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 

} 
+0

sanks,穆罕默德 – 2012-02-03 18:26:46

+0

@PavelShysh,它爲你工作? – 2012-02-03 18:32:46

+0

即時嘗試。我在模擬器上的代碼也工作。但在設備上 - 不是。 – 2012-02-03 19:00:33

3

這是什麼幫助我建立一個適當的工作http通信ssl。

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

如果希望客戶端(Android設備)真(不可盲目)信任主機,公證書需要被加載到器件的密鑰庫,否則設備將不會再跟服務器

你會使用.crt文件,但要與Android KeyStore一起使用,您需要將其轉換爲「bks」。我下面:

// read .crt file from memory 
InputStream inStream = ctx.openFileInput("cetificate.crt"); 

//InputStream inStream = ctx.getAssets().open("wm_loaner.cer"); 
if(inStream != null) 
{ 
    KeyStore cert = CertUtils.ConvertCerToBKS(inStream, "MyAlias", "password".toCharArray()); 
    inStream.close(); 
} 

public static KeyStore ConvertCerToBKS(InputStream cerStream, String alias, char [] password) 
{ 
    KeyStore keyStore = null; 
    try 
    { 
     keyStore = KeyStore.getInstance("BKS", "BC"); 
     CertificateFactory factory = CertificateFactory.getInstance("X.509", "BC"); 
     Certificate certificate = factory.generateCertificate(cerStream); 
     keyStore.load(null, password); 
     keyStore.setCertificateEntry(alias, certificate); 
    } 
    catch .... 
    { 
    } 
    return keyStore;          
} 

證書後,轉換和加載密鑰庫,你可以建立連接

+1

從Android 2.3開始,似乎並沒有受到同樣程度的影響。這裏的解決方案似乎是更安全的良心,通過Bouncy Castle添加證書確實比信任所有更好(這裏是gremlins) – 2012-02-03 20:56:21

+0

但我鋼有一個問題仍然存在: 我有兩個文件 - file.crt和file.pem。 哪一個使用我創建存儲庫(KEYSTORE)? – 2012-02-04 19:19:29

+0

@PavelShysh閱讀更新的答案 – Maxim 2012-02-06 14:24:39

相關問題