web-dev-qa-db-fra.com

Faire une requête HTTPS en utilisant Android Volley

J'essaie de faire une demande https en utilisant ce code:

RequestQueue queue = Volley.newRequestQueue(getApplicationContext());
request = new Request<String>(Request.Method.GET,"https://devblahblahblah.com/service/etc",errListener);

mais j'obtiens cette erreur:

com.Android.volley.NoConnectionError: javax.net.ssl.SSLHandshakeException: Java.security.cert.CertPathValidatorException: ancre de confiance pour chemin de certification non trouvé.

Deux points à noter:

  1. Le certificat HTTPS est valide. Ouvre facilement sans aucun avertissement sur le navigateur.
  2. Le code ci-dessus fonctionne bien avec les liens HTTP.

J'ai réellement besoin de savoir s'il existe des commutateurs/options dans le cadre Android Volley à l'aide desquels je vais utiliser une URL HTTPS?

47
Abdullah Shoaib
15
Ognyan

Ces codes ci-dessous vous seront probablement utiles:

1.Créez une classe HttpsTrustManager qui implémente X509TrustManager:

public class HttpsTrustManager implements X509TrustManager {

    private static TrustManager[] trustManagers;
    private static final X509Certificate[] _AcceptedIssuers = new X509Certificate[]{};

    @Override
    public void checkClientTrusted(
            Java.security.cert.X509Certificate[] x509Certificates, String s)
            throws Java.security.cert.CertificateException {

    }

    @Override
    public void checkServerTrusted(
            Java.security.cert.X509Certificate[] x509Certificates, String s)
            throws Java.security.cert.CertificateException {

    }

    public boolean isClientTrusted(X509Certificate[] chain) {
        return true;
    }

    public boolean isServerTrusted(X509Certificate[] chain) {
        return true;
    }

    @Override
    public X509Certificate[] getAcceptedIssuers() {
        return _AcceptedIssuers;
    }

    public static void allowAllSSL() {
        HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {

            @Override
            public boolean verify(String arg0, SSLSession arg1) {
                return true;
            }

        });

        SSLContext context = null;
        if (trustManagers == null) {
            trustManagers = new TrustManager[]{new HttpsTrustManager()};
        }

        try {
            context = SSLContext.getInstance("TLS");
            context.init(null, trustManagers, new SecureRandom());
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        }

        HttpsURLConnection.setDefaultSSLSocketFactory(context
                .getSocketFactory());
    }

}

2.Ajouter HttpsTrustManager.allowAllSSL() avant de faire une demande https:

HttpsTrustManager.allowAllSSL();
String  tag_string_req = "string_req";
StringRequest strReq = new StringRequest(Request.Method.POST,
        your_https_url, new Response.Listener<String>() {
    @Override
    public void onResponse(String response) {
        Log.d(TAG, "response :"+response);
    }
}, new Response.ErrorListener() {
    @Override
    public void onErrorResponse(VolleyError error) {
        VolleyLog.d(TAG, "Error: " + error.getMessage());
    }
}){
    @Override
    protected Map<String, String> getParams() {
        Map<String, String> params = new HashMap<String, String>();
        params.put("username", "max");
        params.put("password", "123456");
        return params;
    }
};
AppController.getInstance().addToRequestQueue(strReq, tag_string_req);
50
MaxMxx

vous pouvez ajouter cette classe et l'exécuter à partir de la méthode onCreate

new NukeSSLCerts().nuke();

il fera une volée pour faire confiance à tous les certificats SSL.

10
Samrat Das

Si vous utilisez volley et souhaitez une demande HTTPS ou un service certifié SSL, vous pouvez choisir le moyen le plus simple: ->

Étape -> 1. Conserver le fichier .cer dans le dossier res/raw /.

Step -> 2. Utilisez cette méthode et remplacez le nom du fichier .cer par votre fichier .cer, ainsi que votre nom d'hôte.

private SSLSocketFactory getSocketFactory() {

    CertificateFactory cf = null;
    try {

        cf = CertificateFactory.getInstance("X.509");
        InputStream caInput = getResources().openRawResource(R.raw.cert_name);
        Certificate ca;
        try {

            ca = cf.generateCertificate(caInput);
            Log.e("CERT", "ca=" + ((X509Certificate) ca).getSubjectDN());
        } finally {
            caInput.close();
        }


        String keyStoreType = KeyStore.getDefaultType();
        KeyStore keyStore = KeyStore.getInstance(keyStoreType);
        keyStore.load(null, null);
        keyStore.setCertificateEntry("ca", ca);


        String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
        tmf.init(keyStore);


        HostnameVerifier hostnameVerifier = new HostnameVerifier() {
            @Override
            public boolean verify(String hostname, SSLSession session) {

                Log.e("CipherUsed", session.getCipherSuite());
                return hostname.compareTo("10.199.89.68")==0; //The Hostname of your server.

            }
        };


        HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier);
        SSLContext context = null;
        context = SSLContext.getInstance("TLS");

        context.init(null, tmf.getTrustManagers(), null);
        HttpsURLConnection.setDefaultSSLSocketFactory(context.getSocketFactory());

        SSLSocketFactory sf = context.getSocketFactory();


        return sf;

    } catch (CertificateException e) {
        e.printStackTrace();
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (KeyStoreException e) {
        e.printStackTrace();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } catch (KeyManagementException e) {
        e.printStackTrace();
    }

    return  null;
}

Étape -> 3. Remplacez cette ligne "File d'attente RequestQueue = Volley.newRequestQueue (this);" with "RequestQueue queue = Volley.newRequestQueue (this, nouvelle HurlStack (null, getSocketFactory ()));" en demande de volley.

3
Chinki Sai

Jusqu'à présent, la seule réponse à votre question consiste à ajouter un certificat non approuvé en tant que solution. Toutefois, comme votre navigateur ne s'en plaint pas, cela signifie généralement que Volley ne peut pas trouver le certificat intermédiaire qui complète la chaîne de confiance.

Cela m'est arrivé avec les certificats LetsEncrypt. La plupart des navigateurs ont déjà des certificats intermédiaires, donc tout semble aller pour le navigateur, mais il manquait apparemment quelque chose à Volley.

La solution
Ajoutez le certificat intermédiaire à la configuration de votre serveur Web. Pour Apache, vous pouvez suivre cette référence:
https://access.redhat.com/solutions/43575

Pour LetsEncrypt, il s’agit en particulier du fichier suivant: /etc/letsencrypt/live/your.website.com/chain.pemA côté de votre fichier CertificateFile et de votre fichier KeyFile, vous devriez déjà avoir travaillé. Vous avez maintenant cette troisième ligne: 

SSLCertificateChainFile /etc/letsencrypt/live/your.website.com/chain.pem

En ajoutant simplement cette ligne, redémarrer Apache et Volley ne se plaint plus et vous n’avez introduit aucune faille de sécurité!

2
Lappro

Je ne pouvais pas ouvrir le lien fourni par @ Ogre_BGR, mais en naviguant sur le net, j’ai trouvé l’implémentation réelle effectuée dans smanikandan14 Github . Regardez son explication SSl-connection pour en savoir plus.

1
laaptu

Cela peut se produire pour plusieurs raisons, notamment:

  • L'autorité de certification ayant émis le certificat de serveur était inconnue.
  • Le certificat de serveur n'a pas été signé par une autorité de certification, mais a été auto-signé
  • Il manque une autorité de certification intermédiaire à la configuration du serveur.

Doc officiel d'Android

Solution: Vous pouvez fournir un fichier de certificat dans la demande

0
Din Islam Milon