2011-03-28 23 views
7

Attualmente sto scrivendo una parte client per Android (2.2) e un server che utilizza SSL. Sono riuscito a scambiare messaggi tra il server e un normale client, ma Android non sembra essere troppo contento dei certificati autofirmati. Ho cercato StackOverflow e Googled MOLTO e molte persone hanno problemi simili. Tutte le risposte che ho trovato finora non funzionavano o non avevano alcun senso. La maggior parte dei campioni di codice là fuori sono per HTTPS, ma questo non posso usare, dato che ho bisogno di comunicare attraverso un socket (SSLSocket è la mia ipotesi migliore). Ho provato un sacco di codice diverso, ma ora sono tornato di nuovo a zero.Client SSL su Android

Finora ho capito che devo creare un certificato (penso di aver capito bene) e un TrustManager personalizzato. Ovviamente non sono stato in grado di trovare alcun codice funzionante, motivo per cui lo chiedo qui, dato che di solito ci sono alcune persone davvero utili.

Sto cercando una descrizione dettagliata di ciò che dovrebbe essere fatto e un codice che può essere inserito in un codice client Android funzionante.

Grazie in anticipo

risposta

1

ho fatto con il porting nativo browser di Android. Ho appena cambiato il modo in cui viene creato il contesto ssl. ho promesso che metterà anche qualche esempio di lavoro in loco SandroB ma ... :)

https://market.android.com/details?id=org.sandrob

http://code.google.com/p/sandrob/source/browse/misc/examples/HttpsConnection.java

+0

Grazie per la risposta. Ho esaminato il codice a cui ti sei collegato e sembra interessante. Il problema è che utilizza un sacco di classi, che sembrano essere fatte su misura. Ho consultato alcuni di loro su Google e ho scoperto che sono stati implementati in altre librerie. Prendiamo il CertificateChainValidator che sembra essere nel pacchetto android.net.http - ma non è lì. Esiste un esempio di funzionamento completo semplificato, utilizzando le librerie standard? – Casper

1

CertificateChainValidator fa parte delle fonti di Android. Almeno nella versione/tag 2.2.1_r1

Per farlo funzionare è possibile costruire Browser da fonti Android e cambiare quanto SSLContext viene inizializzato nel file di HttpsConnection.java.

Sono necessari keyManager (inizializzati con cerfile/password) e trustManagers (tutti affidabili).

sslContext.engineInit (keyManagers, trustManagers, null, cache, null);

+1

Ciao. Non riesco a importarlo e, secondo http://developer.android.com/reference/android/net/http/package-summary.html, la funzione non sembra esistere. Per quanto ne so, dovrò creare gestori doganali per gestire i certificati, ma devo ancora trovare un codice funzionante. A proposito, sto usando Android 2.2 (API 8). – Casper

1
public class MySSLSocketFactory extends SSLSocketFactory { 
    SSLContext sslContext = SSLContext.getInstance("TLS"); 

    public MySSLSocketFactory(KeyStore truststore) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException { 
     super(truststore); 

     TrustManager tm = new X509TrustManager() { 
      public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { 
      } 

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

      public X509Certificate[] getAcceptedIssuers() { 
       return null; 
      } 
     }; 

     sslContext.init(null, new TrustManager[] { tm }, null); 
    } 

    @Override 
    public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException, UnknownHostException { 
     return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose); 
    } 

    @Override 
    public Socket createSocket() throws IOException { 
     return sslContext.getSocketFactory().createSocket(); 
    } 
} 

E HttpClient è

public HttpClient getNewHttpClient() { 
     try { 
      KeyStore trustStore = KeyStore.getInstance(KeyStore 
        .getDefaultType()); 
      trustStore.load(null, null); 

      SSLSocketFactory sf = new MySSLSocketFactory(trustStore); 
      sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); 

      HttpParams params = new BasicHttpParams(); 
      HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1); 
      HttpProtocolParams.setContentCharset(params, HTTP.UTF_8); 

      SchemeRegistry registry = new SchemeRegistry(); 
      registry.register(new Scheme("http", PlainSocketFactory 
        .getSocketFactory(), 80)); 
      registry.register(new Scheme("https", sf, 443)); 

      ClientConnectionManager ccm = new ThreadSafeClientConnManager(
        params, registry); 

      return new DefaultHttpClient(ccm, params); 
     } catch (Exception e) { 
      return new DefaultHttpClient(); 
     } 
    } 

Spero che ti aiuta.