webentwicklung-frage-antwort-db.com.de

HTTPS-Anfrage mit Android Volley durchführen

Ich versuche, eine https-Anfrage mit diesem Code zu stellen:

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

aber ich erhalte diesen Fehler:

com.Android.volley.NoConnectionError: javax.net.ssl.SSLHandshakeException: Java.security.cert.CertPathValidatorException: Vertrauensanker für Zertifizierungspfad nicht gefunden.

Zwei Punkte zu beachten:

  1. Das HTTPS-Zertifikat ist gültig. Kann leicht ohne Warnung im Browser geöffnet werden.
  2. Der obige Code funktioniert gut mit HTTP-Links.

Ich muss eigentlich wissen, ob es Schalter/Optionen im Android Volley-Framework gibt, mit denen ich eine HTTPS-URL erfolgreich schlagen kann?

47
Abdullah Shoaib

Wahrscheinlich wird dieser Link für Sie hilfreich sein: Android Volley mit selbstsigniertem SSL-Zertifikat verwenden

15
Ognyan

Wahrscheinlich werden die folgenden Codes für Sie hilfreich sein:

1.Erstellen Sie eine HttpsTrustManager-Klasse, die X509TrustManager implementiert:

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. Fügen Sie HttpsTrustManager.allowAllSSL() hinzu, bevor Sie eine https-Anfrage stellen:

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

sie können diese Klasse hinzufügen und sie mit der onCreate-Methode ausführen

new NukeSSLCerts().nuke();

alle SSL-Zertifikate müssen vertrauen.

10
Samrat Das

Wenn Sie Volley verwenden und HTTPS-Anfragen oder einen SSL-zertifizierten Dienst wünschen, können Sie diesen einfachsten Weg wählen: ->

Schritt -> 1. Bewahren Sie die .cer-Datei im Ordner res/raw/auf.

Schritt -> 2. Verwenden Sie diese Methode und ersetzen Sie den .cer-Dateinamen durch Ihre .cer-Datei und ersetzen Sie auch Ihren Hostnamen.

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

Schritt -> 3. Diese Zeile ersetzen "RequestQueue-Warteschlange = Volley.newRequestQueue (this);" mit "RequestQueue queue = Volley.newRequestQueue (dies neuer HurlStack (null, getSocketFactory ()));" auf Anfrage der Salve.

3
Chinki Sai

Die einzige Antwort ist bisher das Hinzufügen eines nicht vertrauenswürdigen Zertifikats als Lösung. Da Ihr Browser sich jedoch nicht beschwert, bedeutet dies normalerweise, dass Volley kein Zwischenzertifikat finden kann, das die gesamte vertrauenswürdige Kette abschließt.

Es ist mir mit LetsEncrypt-Zertifikaten passiert. Die meisten Browser verfügen bereits über Zwischenzertifikate, so dass im Browser alles gut aussieht, aber Volley hat anscheinend etwas gefehlt.

Die Lösung
Fügen Sie das Zwischenzertifikat Ihrer Webserver-Konfiguration hinzu. Für Apache können Sie dieser Referenz folgen:
https://access.redhat.com/solutions/43575

Bei LetsEncrypt handelt es sich speziell um diese Datei: /etc/letsencrypt/live/your.website.com/chain.pemSo. Neben Ihrer CertificateFile und KeyFile sollten Sie bereits arbeiten, Sie haben jetzt diese dritte Zeile: 

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

Das Hinzufügen dieser Zeile, der Neustart von Apache und Volley beklagen sich nicht mehr und Sie haben keine Sicherheitslücken eingeführt!

2
Lappro

Ich konnte den von @ Ogre_BGR bereitgestellten Link nicht öffnen, aber beim Durchsuchen des Netzes fand ich die eigentliche Implementierung in smanikandan14 Github . Schauen Sie sich seine SSl-Verbindungserklärung an, um mehr darüber zu erfahren.

1
laaptu

Dies kann aus verschiedenen Gründen geschehen, darunter:

  • Die Zertifizierungsstelle, die das Serverzertifikat ausgestellt hat, war unbekannt
  • Das Serverzertifikat wurde nicht von einer Zertifizierungsstelle signiert, war jedoch selbst signiert
  • Bei der Serverkonfiguration fehlt eine Zwischenzertifizierungsstelle

Offizielles Dokument von Android

Lösung: Sie können eine Zertifikatsdatei innerhalb der Anforderung bereitstellen

0
Din Islam Milon

Wenn Sie auf ein solches Problem stoßen und Letsencrypt für Ihr SSL und node.js für Ihren Webserver verwenden, versuchen Sie dies. Vorausgesetzt, Sie haben so etwas. Ich habe dies durch Hinzufügen der Zeile const chain = fs ... behoben. Hoffe, das hilft

...
const app = express();
const privateKey  = fs.readFileSync('ssl/privkey.pem', 'utf8');
const certificate = fs.readFileSync('ssl/cert.pem', 'utf8');
const chain = fs.readFileSync('ssl/chain.pem', 'utf8');
const credentials = {key: privateKey, cert: certificate, ca: chain};
...
var httpsServer = https.createServer(credentials, app);
0
nada