2016-07-11 1 views
2

Récemment, je fait un certificat auto-roussi dans le serveur web Apache en utilisant ce tutoriel:certificat auto-signé android ne fonctionnera pas

http://theheat.dk/blog/?p=1023&cpage=1

service Web nécessitent un certificat d'ouvrir. dans le navigateur tout va bien. J'ai importé des certificats et le site s'ouvrira.

J'ai fait le fichier BKS à partir de rootCA.crt, client.crt, winter fell.crt, Mais personne ne travaille.
Dans Android Je reçois

SSL3_GET_CLIENT_CERTIFICATE: par les pairs n'a pas retourné un certificat Aucune autorité de certification connu au serveur pour la vérification?

message d'erreur dans le journal Apache.

Il semble que mon problème concerne la combinaison de certificats à envoyer au serveur! dans le navigateur j'utilise client et rootCA, comment puis-je les combiner pour envoyer au serveur web?

Mon code:

try { 
     DefaultHttpClient httpclient = new MyHttpClient(getApplicationContext()); 
     HttpGet get = new HttpGet("https://xxx.xxx.xxx.xxx/index.php"); 

     try { 
      HttpResponse response = httpclient.execute(get); 
     } catch (ClientProtocolException e) { 
      System.out.println(e.getMessage()); 
     } catch (IOException e) { 
      System.out.println(e.getMessage()); 
     } 
     return "OK"; 


    } catch (Exception err) { 
     return "Err"; 
    } 

Et

public class MyHttpClient extends DefaultHttpClient { 

final Context context; 

public MyHttpClient(Context context) { 
    this.context = context; 
} 

@Override 
protected ClientConnectionManager createClientConnectionManager() { 
    SchemeRegistry registry = new SchemeRegistry(); 
    // Register for port 443 our SSLSocketFactory with our keystore 
    // to the ConnectionManager 
    registry.register(new Scheme("https", newSslSocketFactory(), 443)); 
    return new SingleClientConnManager(getParams(), registry); 
} 

private SSLSocketFactory newSslSocketFactory() { 
    try { 
     // Get an instance of the Bouncy Castle KeyStore format 
     KeyStore trusted = KeyStore.getInstance("BKS"); 
     // Get the raw resource, which contains the keystore with 
     // your trusted certificates (root and any intermediate certs) 
     InputStream in = context.getResources().openRawResource(R.raw.comb); 
     try { 
      // Initialize the keystore with the provided trusted certificates 
      // Also provide the password of the keystore 
      trusted.load(in, "mysecret".toCharArray()); 
     } finally { 
      in.close(); 
     } 

     // Pass the keystore to the SSLSocketFactory. The factory is responsible 
     // for the verification of the server certificate. 
     SSLSocketFactory sf = new SSLSocketFactory(trusted); 
     // Hostname verification from certificate 
     // http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html#d4e506 
     //sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); 
     HttpsURLConnection.setDefaultHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); 

     return sf; 
    } catch (Exception e) { 
     throw new AssertionError(e); 
    } 
} 

Votre aide vraiment apprécié!

+0

Postez votre code. –

+0

mon code attaché – Mehdi

+0

Quelle version d'Android rencontrez-vous sur ce problème? –

Répondre

1

Utilisez ci-dessous la classe personnalisée SSLSocketFactory.

public class AndroidSSLSocketFactory extends SSLSocketFactory { 
    TrustManagerFactory tmf = TrustManagerFactory.getInstance(
      "X509"); 
    public AndroidSSLSocketFactory(KeyStore truststore) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException { 
     super(truststore); 
     tmf.init(truststore); 
     TrustManager[] trustManagers = tmf.getTrustManagers(); 
     final X509TrustManager origTrustmanager = (X509TrustManager)trustManagers[0]; 
     TrustManager tm = new X509TrustManager() { 
      public java.security.cert.X509Certificate[] getAcceptedIssuers() { 
       return origTrustmanager.getAcceptedIssuers(); 
      } 

      @Override 
      public void checkClientTrusted(
        java.security.cert.X509Certificate[] chain, String authType) 
        throws CertificateException { 
       origTrustmanager.checkClientTrusted(chain, authType); 
      } 

      @Override 
      public void checkServerTrusted(
        java.security.cert.X509Certificate[] chain, String authType) 
        throws CertificateException { 
       origTrustmanager.checkServerTrusted(chain, authType); 
      } 
     }; 
     SSLContext sslContext = SSLContext.getInstance("TLS"); 
     sslContext.init(null, new TrustManager[]{tm}, null); 
    } 
} 

Cette classe gère la sécurité de la couche Transport entre le serveur et Android via le certificat X509.

Utilisez-le dans votre méthode newSslSocketFactory(). Remplacer

SSLSocketFactory sf = new SSLSocketFactory(trusted);

Avec

SSLSocketFactory sf = new AndroidSSLSocketFactory(trusted); 

Espérons que cela vous aidera.

Info: -HttpClient est dépréciée à partir d'Android 6.0, vous devez utiliser HttpURLConnection à la place. .

Mise à jour 1: - Comme par this lien afin de travailler avec le certificat auto-signé Vous pouvez créer votre propre TrustManager. Alors faites des changements dans le code de TrustManager. Cela pourrait aider les futurs utilisateurs.

+0

Non. wont changé n'importe quoi – Mehdi

+0

@Igor Ganapolsky Merci d'avoir attiré mon attention là-dessus, je viens de renvoyer null de getAcceptedIssuers() car il fera confiance à TrustManager de tous les certificats. Comme il ne fonctionne pas pour Mehdi, je vais mettre à jour ma réponse bientôt. –

+0

J'ai mis à jour ma réponse. –