2012-02-03 81 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

相关问题