2012-12-17 12 views
6

Najpierw musiałem przyznać, że wiem, że akceptowanie wszystkich certyfikatów może być uznane za pozbawione zabezpieczeń. Mamy "prawdziwe" certyfikaty, ale tylko na naszych systemach live. Certyfikaty w naszych systemach testowych są z podpisem własnym. Tak długo, jak się rozwijamy, musimy używać serwerów testowych, co zmusza mnie do rodzaju wyłączania certyfikatów.akceptuj samopodpisane certyfikaty SSL-> gdzie ustawić domyślny TrustManager

Widziałem wiele rzeczy tutaj na Stackoverflow i w całym Internecie, które próbują zrobić to samo: Akceptowanie certyfikatów SSL. Jednak żadna z tych odpowiedzi nie wydaje się dotyczyć mojego problemu, ponieważ nie mam problemu z HTTPSUrlConnections.

Jeśli robię żądanie kodu zazwyczaj wygląda następująco (skomentował dla clearification):

//creates an HTTP-Post with an URL 
HttpPost post = createBaseHttpPost(); 
//loads the request Data inside the httpPost 
post.setEntity(getHttpPostEntity()); 
//appends some Headers like user-agend or Request UUIDs 
appendHeaders(post); 

HttpClient client = new DefaultHttpClient(); 
//mResponse is a custom Object which is returned 
//from the custom ResponseHandler(mResponseHandler) 
mResponse = client.execute(post, mResponseHandler); 
return mResponse; 

czytałem że należy wstrzykiwać własne TrustManager i X509HostnameVerivier. Stworzyłem je tak:

private static final TrustManager[] TRUST_ALL_CERTS = new TrustManager[]{ 
     new X509TrustManager() { 

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

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

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

    }; 

    private static X509HostnameVerifier ACCEPT_ALL_HOSTNAMES = 
      new X509HostnameVerifier() { 

       public void verify(String host, String[] cns, String[] subjectAlts) 
         throws SSLException { 
       } 

       public void verify(String host, X509Certificate cert) throws SSLException { 
       } 

       public void verify(String host, SSLSocket ssl) throws IOException { 
       } 

       public boolean verify(String host, SSLSession session) { 
        return true; 
       } 
      }; 

Gdybym wstrzyknąć HostnameVerifier wewnątrz moją prośbę tak (klient jest DefaultHttpClient z góry)

SSLSocketFactory ssl = (SSLSocketFactory)client.getConnectionManager().getSchemeRegistry().getScheme("https").getSocketFactory(); 
ssl.setHostnameVerifier(ACCEPT_ALL_HOSTNAMES); 

odpowiedź odwraca się od „hosta ** nie pasuje” na "Złą prośbę". Domyślam się, że muszę ustawić TrustManager, ale nie mam bladego pojęcia, gdzie ustawić go wewnątrz mojej prośby, ponieważ nie używam HttpsUrlConnections wspomnianych wszędzie, gdzie go szukałem.

+0

Zamiast dodawać kod, który zezwala na każdy certyfikat (to jest kod, który może nigdy nie zostać usunięty, zwłaszcza jeśli zapomnisz o tym, gdy nadejdzie termin), możesz rozważyć uruchomienie własnego przetestuj CA. Trzeba będzie zaimportować ten testowy certyfikat CA do magazynu zaufanych certyfikatów, ale jest to bardziej realistyczny test, w tym nazwy hostów (i mniej podatny na pozostawienie złego kodu w wydanym produkcie). Istnieją narzędzia, które ułatwiają zarządzanie małymi urzędami certyfikacji. – Bruno

Odpowiedz

9

Nie, nie wymusza to wyłączenia sprawdzania poprawności, zmusza do prawidłowego wdrożenia sprawdzania poprawności. Nie wolno ślepo akceptować wszystkich certyfikatów. I nie, twoja sprawa nie jest inna, po prostu musisz zaufać certyfikatowi, któremu Android domyślnie nie ufa.

Używasz HttpClient, więc API do ustawiania menedżera zaufania są nieco inne niż HttpsURLConnection, ale procedura jest taka sama:

  1. załadować plik kluczy z zaufanych certyfikatów (certyfikatów z podpisem własnym Twojego serwera)
  2. Zainicjuj z nim KeyStore.
  3. Utwórz SocketFactory za pomocą KeyStore z 2.
  4. Ustaw bibliotekę klienta HTTP, aby używać jej podczas tworzenia gniazd SSL.

Jest to opisane w dokumentacji Android: http://developer.android.com/reference/org/apache/http/conn/ssl/SSLSocketFactory.html

Bardziej szczegółowy artykuł na ten temat, pokazuje, jak utworzyć plik sklepu zaufanie: http://blog.crazybob.org/2010/02/android-trusting-ssl-certificates.html

Niektóre informacje tło i przykładowy kod: http://nelenkov.blogspot.com/2011/12/using-custom-certificate-trust-store-on.html

To jest kod potrzebny do zainicjowania HttpClient:

KeyStore localTrustStore = KeyStore.getInstance("BKS"); 
InputStream in = getResources().openRawResource(R.raw.mytruststore); 
localTrustStore.load(in, TRUSTSTORE_PASSWORD.toCharArray()); 

SchemeRegistry schemeRegistry = new SchemeRegistry(); 
schemeRegistry.register(new Scheme("http", PlainSocketFactory 
       .getSocketFactory(), 80)); 
SSLSocketFactory sslSocketFactory = new SSLSocketFactory(localTrustStore); 
schemeRegistry.register(new Scheme("https", sslSocketFactory, 443)); 
HttpParams params = new BasicHttpParams(); 
ClientConnectionManager cm = 
    new ThreadSafeClientConnManager(params, schemeRegistry); 

HttpClient client = new DefaultHttpClient(cm, params); 

W tym momencie nie masz wymówek, aby ufać wszystkim certyfikatom.Jeśli to zrobisz, to wszystko na ciebie :)

Powiązane problemy