2016-02-20 10 views
15

Google poinformowała, że ​​mam niebezpiecznego realizację X509TrustManager interfejsu w mojej aplikacji Android i muszą zmienić swój kod w następujący sposób:Jak naprawić niebezpieczny realizację X509TrustManager w Android app

Aby prawidłowo obsługiwać certyfikat SSL sprawdzanie poprawności, zmień swój kod w metodzie check_verServerTansted niestandardowego interfejsu X509TrustManager na podnieś wyjątek CertificateException lub IllegalArgumentException, gdy certyfikat nie będzie spełniał Twoich oczekiwań . W przypadku pytań technicznych, można dodawać do przepełnienia stosu i używać tagów „android-security” i „TrustManager.”

Jak następujący kod zostać zmodyfikowane, aby rozwiązać powyższy problem?

public EasySSLSocketFactory(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; 
     } 
    }; 

    mContext.init(null, new TrustManager[] { tm }, null); 
} 
+0

Spotykam się również z tym problemem, czy masz rozwiązanie? – zys

+4

"W jaki sposób można zmodyfikować poniższy kod, aby naprawić powyższy problem?" - usuwasz to. – CommonsWare

Odpowiedz

20

Mam rozwiązać to za pomocą następującego kodu:

public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { 
       try { 
        chain[0].checkValidity(); 
       } catch (Exception e) { 
        throw new CertificateException("Certificate not valid or trusted."); 
       } 
      } 
+0

To również rozwiązało ostrzeżenie w Google Play. – StevenTB

+0

Tak, to właśnie rozumiem przez "rozwiązany" :) – Nabeel

+0

@Glowcall, w którym powinienem napisać powyżej kodu w aplikacji, aby rozwiązać problem? Mam na myśli, pod jaką aktywność? – anddev

0

muszę spełnić ten problem.If kod jest tak:

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

będzie akceptować wszystkie zaświadczenia i że jest to zły pomysł, więc google wysłać Ci maila. Możemy dokonać zmiany, aby zaakceptować także samopodpisany certyfikat. Rozwiązałem go, here is my question and my solution

+0

Dzięki, ale zobacz moją odpowiedź na prostszą poprawkę.Ostrzeżenie z Google zniknęło z konsoli programisty Play. – Nabeel

+0

Witam, proszę powiedz, gdzie powinienem umieścić powyższy kod. – Alpesh

+0

Zobacz rozwiązanie, które podałem linku – zys

1

przypadku napotkania tego z zewnętrznej biblioteki używasz, sprawdź czy appache libraray jest przyczyną.

Dla mnie biblioteka apache spowodowała błąd: używałam przestarzałej klasy - MultipartEntity. Ta klasa używa SSLContextBuilder , która używa TrustManagerDelegate. TrustManagerDelegate implementuje X509TrustManager, który powoduje "niebezpieczną implementację TrustManager" podczas przesyłania aplikacji do sklepu Google Play.

Rozwiązaniem jest: zamiast wycofanej klasy MultipartEntity, użyj MultipartEntityBuilder.

Na przykład:

MultipartEntity httpMultipart = new MultipartEntity(); 
String contentType = httpMultipart.getContentType().getValue(); 

Zostanie zastąpiony przez:

MultipartEntityBuilder httpMultipart = new MultipartEntityBuilder(); 
String contentType = httpMultipart.build().getContentType().getValue(); 
+0

Tak, masz rację, ja również mam do czynienia z tym samym problemem. –

-1

Jeśli używasz HttpClient następnie roztwór @Nabeel jest bardzo ładny, ale jeśli używasz HttpsUrlConnection czym ten kod jest bardzo miło:

import android.util.Log; 

import java.security.SecureRandom; 
import java.security.cert.CertificateException; 
import java.security.cert.X509Certificate; 

import javax.net.ssl.HostnameVerifier; 
import javax.net.ssl.HttpsURLConnection; 
import javax.net.ssl.SSLContext; 
import javax.net.ssl.SSLSession; 
import javax.net.ssl.TrustManager; 
import javax.net.ssl.X509TrustManager; 

/** 
* TrustManager that accepts all certificates and hosts. 
* Useful when you want to use HTTPS but you have self-signed certificates. 
* Works with HttpsUrlConnection. 
* Use at your own risk and only for development. 
* 
* @author gotev (Aleksandar Gotev) 
*/ 
public class AllCertificatesAndHostsTruster implements TrustManager, X509TrustManager { 

    @Override 
    public final void checkClientTrusted(final X509Certificate[] xcs, final String string) 
      throws CertificateException { 
    } 

    @Override 
    public final void checkServerTrusted(final X509Certificate[] xcs, final String string) 
      throws CertificateException { 
    } 

    @Override 
    public final X509Certificate[] getAcceptedIssuers() { 
     return new X509Certificate[0]; 
    } 

    /** 
    * Gets an {@link SSLContext} which trusts all certificates. 
    * @return {@link SSLContext} 
    */ 
    public static SSLContext getSSLContext() { 
     final TrustManager[] trustAllCerts = 
       new TrustManager[] {new AllCertificatesAndHostsTruster()}; 

     try { 
      final SSLContext context = SSLContext.getInstance("SSL"); 
      context.init(null, trustAllCerts, new SecureRandom()); 
      return context; 

     } catch (Exception exc) { 
      Log.e("CertHostTruster", "Unable to initialize the Trust Manager to trust all the " 
        + "SSL certificates and HTTPS hosts.", exc); 
      return null; 
     } 
    } 

    /** 
    * Creates an hostname verifier which accepts all hosts. 
    * @return {@link HostnameVerifier} 
    */ 
    public static HostnameVerifier getAllHostnamesVerifier() { 
     return new HostnameVerifier() { 
      @Override 
      public boolean verify(String hostname, SSLSession session) { 
       return true; 
      } 
     }; 
    } 

    /** 
    * Call this method once before all your network calls 
    * to accept all the self-signed certificates in HTTPS connections. 
    */ 
    public static void apply() { 
     final TrustManager[] trustAllCerts = 
       new TrustManager[] {new AllCertificatesAndHostsTruster()}; 

     try { 
      final SSLContext context = SSLContext.getInstance("SSL"); 
      context.init(null, trustAllCerts, new SecureRandom()); 
      HttpsURLConnection.setDefaultSSLSocketFactory(context.getSocketFactory()); 
      HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() { 

       @Override 
       public boolean verify(String hostname, SSLSession session) { 
        return true; 
       } 
      }); 

     } catch (Exception exc) { 
      Log.e("CertHostTruster", "Unable to initialize the Trust Manager to trust all the " 
        + "SSL certificates and HTTPS hosts.", exc); 
     } 
    } 
} 

Źródło: https://gist.github.com/gotev/6784c1303793c6ee9e56

Następnie używać certyfikatów z podpisem własnym, wystarczy wywołać:

AllCertificatesAndHostsTruster.apply(); 

przed wszystkimi połączeniami sieciowymi.

+0

Jest to bardzo złe i nie powinno być używane do niczego, jeśli masz podpisany przez siebie certyfikat, a następnie sprawdź ten certyfikat, akceptując wszystko, co czyni SSL bezcelowym. – Nohus

+0

Tak, to jest dobra odpowiedź, uratowałeś mój czas – Jeyaseelan

Powiązane problemy