2011-03-28 18 views
7

Obecnie piszę część klienta dla Androida (2.2) i serwer używający SSL. Udało mi się wymieniać wiadomości między serwerem a normalnym klientem, ale Android nie wydaje się być zbyt szczęśliwy z powodu samopodpisanych certyfikatów. Szukałem Stackoverflow i Googled wiele i wiele osób ma podobne problemy. Wszystkie odpowiedzi, które do tej pory znalazłem albo nie działały, albo nie miały żadnego sensu. Większość próbek kodu jest dostępnych dla HTTPS, ale nie mogę tego użyć, ponieważ potrzebuję komunikować się przez gniazdo (SSLSocket jest moim najlepszym domysłem). Próbowałem już wielu różnych kodów, ale teraz znowu wracam do zera.Klient SSL na Androida

Do tej pory doszedłem do wniosku, że muszę stworzyć certyfikat (myślę, że mam to prawo) i niestandardowy TrustManager. Oczywiście nie udało mi się znaleźć żadnego działającego kodu, dlatego proszę tutaj, ponieważ zwykle są naprawdę pomocni ludzie.

Szukam szczegółowego opisu tego, co ma być zrobione, oraz kodu, który można przekształcić w działający kod klienta Android.

góry dzięki

Odpowiedz

1

Zrobiłem to z przeniesieniem natywną Android Browser. Właśnie zmieniłem sposób tworzenia kontekstu ssl. Obiecałam, że będę również umieścić jakiś przykład pracuje na miejscu SandroB ale ... :)

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

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

+0

Dziękuję za odpowiedź. Sprawdziłem kod, z którym się łączyłeś i wygląda to interesująco. Problem polega na tym, że używa wielu klas, które wydają się być wykonane na zamówienie. Sprawdziłem niektóre z nich w Google i odkryłem, że zostały zaimplementowane w innych bibliotekach. Przyjmijmy, że CertificateChainValidator prawdopodobnie znajduje się w pakiecie android.net.http - ale go tam nie ma. Czy istnieje uproszczony pełny przykład pracy, używając standardowych bibliotek? – Casper

1

CertificateChainValidator jest częścią źródeł android. Przynajmniej w wersji/tag 2.2.1_r1

Aby pracować można zbudować ze źródeł Browser android i zmienić tylko jak SSLContext jest inicjowany w HttpsConnection.java pliku.

Potrzebujesz keyManagers (zainicjalizowany przy pomocy cerfile/password) i trustManagers (trust all).

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

+1

Witam. Nie mogę go zaimportować, a według http://developer.android.com/reference/android/net/http/package-summary.html ta funkcja nie istnieje. O ile mi wiadomo, będę musiał stworzyć menedżerów celnych, którzy będą obsługiwać certyfikaty, ale muszę jeszcze znaleźć jakiś działający kod. Korzystam z Androida 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(); 
    } 
} 

I httpclient jest

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(); 
     } 
    } 

Nadzieję, że to pomaga.