it-swarm.com.de

Android SSL HttpGet (Kein Peer-Zertifikat) Fehler OR (Verbindung von Peer geschlossen) Fehler

Ich versuche, ein einfaches HttpGet zu machen, um eine Webseite zu lesen. Ich habe dies auf iOS und arbeitet an Android über http, aber nicht https.

Die URL ist eine interne Netzwerk-IP und ein benutzerdefinierter Port, so dass ich mit http wie folgt lesen kann, indem ich den Pfad http://ipaddress:port/MyPage.html Verwende.

HttpClient httpclient = new DefaultHttpClient(httpParameters);
                    HttpResponse response;
        String responseString = null;
        try {
            // Try connection
            HttpGet get = new HttpGet(params[0].path);
            get.addHeader("Authorization",
                    "Basic "
                            + Base64.encodeBytes(new String(params[0].username + ":" + params[0].password)
                                    .getBytes()));
        response = httpclient.execute(get);
        StatusLine statusLine = response.getStatusLine();
        if (statusLine.getStatusCode() == HttpStatus.SC_OK) {
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            response.getEntity().writeTo(out);
            out.close();
            responseString = out.toString();
        } else {
            // Closes the connection.
            response.getEntity().getContent().close();
            throw new IOException(statusLine.getReasonPhrase());
        }
    } catch (ClientProtocolException e) {
        Log.e(TAG, "ClientProtocolException");
        this.e = e;
    } catch (IOException e) {
        Log.e(TAG, "IOException");
        this.e = e;
    }
    return responseString;

Wenn ich versuche, https zu verwenden, wird der Fehler No peer certificate Angezeigt. Also habe ich versucht, diesen Code zu verwenden: HttpClient httpclient = new DefaultHttpClient(httpParameters);

private HttpClient createHttpClient() {
        try {
            KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
            trustStore.load(null, null);

            SSLSocketFactory sf = new MySSLSocketFactory(trustStore);
            sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

            HttpParams params = new BasicHttpParams();
            HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
            HttpProtocolParams.setContentCharset(params, HTTP.DEFAULT_CONTENT_CHARSET);
            HttpProtocolParams.setUseExpectContinue(params, true);

            SchemeRegistry schReg = new SchemeRegistry();
            schReg.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
            schReg.register(new Scheme("https", sf, 8080));
            ClientConnectionManager conMgr = new ThreadSafeClientConnManager(params, schReg);

            return new DefaultHttpClient(conMgr, params);

        } catch (Exception e) {
            return new DefaultHttpClient();
        }
    }

aber das gibt mir einen Connection closed by peer Fehler.

Was mache ich falsch? Ich kann das Zertifikat ignorieren, da es sich um ein internes Netzwerk mit selbstsigniertem Zertifikat handelt. Ich habe jedoch keine Kontrolle über vert und Benutzer meiner App verfügen möglicherweise über andere Zertifikate. Daher muss ich es wirklich automatisch akzeptieren oder umgehen.

Vielen Dank

EDIT ------------------------------

Nachdem Sie My-Name-Is ausprobiert haben, antworten Sie wie folgt: Ich habe eine CustomX509TrustManager-Klasse wie vorgeschlagen erstellt und dann einen benutzerdefinierten HttpClient damit erstellt:

private HttpClient sslClient(HttpClient client) {
        try {
            CustomX509TrustManager tm = new CustomX509TrustManager();
            SSLContext ctx = SSLContext.getInstance("TLS");
            ctx.init(null, new TrustManager[] { tm }, null);
            SSLSocketFactory ssf = new MySSLSocketFactory(ctx);
            ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
            ClientConnectionManager ccm = client.getConnectionManager();
            SchemeRegistry sr = ccm.getSchemeRegistry();
            sr.register(new Scheme("https", ssf, 8080));
            return new DefaultHttpClient(ccm, client.getParams());
        } catch (Exception ex) {
            return null;
        }
    }

Und zum Schluss benutze diesen HttpClient wie folgt:

private class httpGETTask extends AsyncTask<GetParams, Void, String> {
private Exception e = null;

@Override
protected String doInBackground(GetParams... params) {
    // Set connection parameters
    HttpParams httpParameters = new BasicHttpParams();
    int timeoutConnection = 15000;
    HttpConnectionParams.setConnectionTimeout(httpParameters, timeoutConnection);
    int timeoutSocket = 15000;
    HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket);

    Log.v(TAG, params[0].path);
    HttpClient httpclient = new DefaultHttpClient(httpParameters);
    httpclient = sslClient(httpclient);

    HttpResponse response;
    String responseString = null;
    try {
        // Try connection
        HttpGet get = new HttpGet(params[0].path);
        get.addHeader("Authorization",
                "Basic "
                        + Base64.encodeBytes(new String(params[0].username + ":" + params[0].password)
                                .getBytes()));

        response = httpclient.execute(get);
        StatusLine statusLine = response.getStatusLine();
        if (statusLine.getStatusCode() == HttpStatus.SC_OK) {
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            response.getEntity().writeTo(out);
            out.close();
            responseString = out.toString();
        } else {
            // Closes the connection.
            response.getEntity().getContent().close();
            throw new IOException(statusLine.getReasonPhrase());
        }
    } catch (ClientProtocolException e) {
        Log.e(TAG, "ClientProtocolException");
        this.e = e;
    } catch (IOException e) {
        Log.e(TAG, "IOException");
        this.e = e;
    }
    return responseString;

Der protokollierte Pfad hat das Format https://ipaddress:8080/Page.html. Es wird jedoch die Fehlermeldung Connection closed By Peer Angezeigt:

05-24 08: 20: 32.500: E/ConnectionHelper (1129): IOException 05-24 08: 20: 32.550: E/ConnectionHelper (1129): Ausnahme beim Laden von Inhalten 05-24 08: 20: 32.550: E/ConnectionHelper (1129 ): javax.net.ssl.SSLException: Verbindung von Peer geschlossen 05-24 08: 20: 32.550: E/ConnectionHelper (1129): at org.Apache.harmony.xnet.provider.jsse.NativeCrypto.SSL_do_handshake (native Methode) 05-24 08: 20: 32.550: E/ConnectionHelper (1129): at org.Apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake (OpenSSLSocketImpl.Java:410) 05-24 08: 20: 32.550: E/ConnectionHelper (1129): bei org.Apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl $ SSLInputStream. (OpenSSLSocketImpl.Java:643) 05-24 08: 20: 32.550: E/ConnectionHelper (1129): bei org.Apache. harmony.xnet.provider.jsse.OpenSSLSocketImpl.getInputStream (OpenSSLSocketImpl.Java:614) 05-24 08: 20: 32.550: E/ConnectionHelper (1129): at org.Apache.http.impl.io.SocketInputBuffer. (SocketInputBuffer. Java: 70) 05-24 08: 20: 32.550: E/ConnectionHelper (1129): at org.Apache.http.impl.Soc ketHttpClientConnection.createSessionInputBuffer (SocketHttpClientConnection.Java:83) 05-24 08: 20: 32.550: E/ConnectionHelper (1129): at org.Apache.http.impl.conn.DefaultClientConnection.createSessionInputBuffer (DefaultClientConnection.createSessionInputBuffer) 08: 20: 32.550: E/ConnectionHelper (1129): at org.Apache.http.impl.SocketHttpClientConnection.bind (SocketHttpClientConnection.Java:106) 05-24 08: 20: 32.550: E/ConnectionHelper (1129): at org .Apache.http.impl.conn.DefaultClientConnection.openCompleted (DefaultClientConnection.Java:129) 05-24 08: 20: 32.550: E/ConnectionHelper (1129): at org.Apache.http.impl.conn.DefaultClientConnectionOperator.openConnection ( DefaultClientConnectionOperator.Java:172) 05-24 08: 20: 32.550: E/ConnectionHelper (1129): at org.Apache.http.impl.conn.AbstractPoolEntry.open (AbstractPoolEntry.Java:164) 05-24 08:20: 32.550: E/ConnectionHelper (1129): at org.Apache.http.impl.conn.AbstractPooledConnAdapter.open (AbstractPooledConnAdapter.Java:119) 05-24 08: 20: 32.550: E/ConnectionHelper ( 1129): at org.Apache.http.impl.client.DefaultRequestDirector.execute (DefaultRequestDirector.Java:360) 05-24 08: 20: 32.550: E/ConnectionHelper (1129): at org.Apache.http.impl.client .AbstractHttpClient.execute (AbstractHttpClient.Java:555) 05-24 08: 20: 32.550: E/ConnectionHelper (1129): at org.Apache.http.impl.client.AbstractHttpClient.execute (AbstractHttpClient.Java:487) 05- 24 08: 20: 32.550: E/ConnectionHelper (1129): at org.Apache.http.impl.client.AbstractHttpClient.execute (AbstractHttpClient.Java:465) 05-24 08: 20: 32.550: E/ConnectionHelper (1129) : at com.d_apps.my_app.connection_helpers.ConnectionHelper $ httpGETTask.doInBackground (ConnectionHelper.Java:114)

28
Darren

Die folgende Quelle sollte Ihr Problem beheben.

import Android.app.Activity;
import Android.widget.EditText;
import Android.os.Bundle;
import org.Apache.http.HttpResponse;
import org.Apache.http.Header
import Java.io.InputStream;
import Java.io.BufferedReader;
import Java.io.InputStreamReader;
import Android.util.Log;
import Android.view.Menu;
public class MainActivity extends Activity {

    private EditText text;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        text = (EditText) findViewById(R.id.editText1);
        connect();
    }

    private void connect(){
        try {
            DataLoader dl = new DataLoader();
            String url = "https://IpAddress";
            HttpResponse response = dl.secureLoadData(url); 

            StringBuilder sb = new StringBuilder();
            sb.append("HEADERS:\n\n");

            Header[] headers = response.getAllHeaders();
            for (int i = 0; i < headers.length; i++) {
                Header h = headers[i];
                sb.append(h.getName()).append(":\t").append(h.getValue()).append("\n");
            }

            InputStream is = response.getEntity().getContent();
            StringBuilder out = new StringBuilder();
            BufferedReader br = new BufferedReader(new InputStreamReader(is));
            for (String line = br.readLine(); line != null; line = br.readLine())
                out.append(line);
            br.close();

            sb.append("\n\nCONTENT:\n\n").append(out.toString()); 

            Log.i("response", sb.toString());
            text.setText(sb.toString());

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }

}


import Android.app.Application;
import Android.content.Context;
import Java.io.InputStream;
public class MeaApplication extends Application {

    private static Context context;

    @Override
    public void onCreate() {
        super.onCreate();
        MeaApplication.context = getApplicationContext();
    }

    public static Context getAppContext() {
        return MeaApplication.context;
    }

    public static InputStream loadCertAsInputStream() {
        return MeaApplication.context.getResources().openRawResource(
                R.raw.meacert);
    }

}


import org.Apache.http.conn.ssl.SSLSocketFactory;
import javax.net.ssl.SSLContext;
import Java.security.KeyStore;
import Java.security.NoSuchAlgorithmException;
import Java.security.KeyManagementException;
import Java.security.KeyStoreException;
import Java.security.UnrecoverableKeyException;
import javax.net.ssl.TrustManager;
import Java.net.Socket;
import Java.io.IOException;
import Java.net.UnknownHostException;
/**
 * Taken from: http://janis.peisenieks.lv/en/76/english-making-an-ssl-connection-via-Android/
 *
 */
public class CustomSSLSocketFactory extends SSLSocketFactory {
    SSLContext sslContext = SSLContext.getInstance("TLS");

    public CustomSSLSocketFactory(KeyStore truststore)
            throws NoSuchAlgorithmException, KeyManagementException,
            KeyStoreException, UnrecoverableKeyException {
        super(truststore);

        TrustManager tm = new CustomX509TrustManager();

        sslContext.init(null, new TrustManager[] { tm }, null);
    }

    public CustomSSLSocketFactory(SSLContext context)
            throws KeyManagementException, NoSuchAlgorithmException,
            KeyStoreException, UnrecoverableKeyException {
        super(null);
        sslContext = context;
    }

    @Override
    public Socket createSocket(Socket socket, String Host, int port,
            boolean autoClose) throws IOException, UnknownHostException {
        return sslContext.getSocketFactory().createSocket(socket, Host, port,
                autoClose);
    }

    @Override
    public Socket createSocket() throws IOException {
        return sslContext.getSocketFactory().createSocket();
    }
}


import javax.net.ssl.X509TrustManager;
import Java.security.cert.CertificateException;
import Java.security.cert.X509Certificate;
import Java.io.IOException;
import Java.io.InputStream;
import Java.security.cert.CertificateFactory;
public class CustomX509TrustManager implements X509TrustManager {

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

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

        // Here you can verify the servers certificate. (e.g. against one which is stored on mobile device)

        // InputStream inStream = null;
        // try {
        // inStream = MeaApplication.loadCertAsInputStream();
        // CertificateFactory cf = CertificateFactory.getInstance("X.509");
        // X509Certificate ca = (X509Certificate)
        // cf.generateCertificate(inStream);
        // inStream.close();
        //
        // for (X509Certificate cert : certs) {
        // // Verifing by public key
        // cert.verify(ca.getPublicKey());
        // }
        // } catch (Exception e) {
        // throw new IllegalArgumentException("Untrusted Certificate!");
        // } finally {
        // try {
        // inStream.close();
        // } catch (IOException e) {
        // e.printStackTrace();
        // }
        // }
    }

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

}


import org.Apache.http.HttpResponse;
import org.Apache.http.client.ClientProtocolException;
import Java.io.IOException;
import Java.security.NoSuchAlgorithmException;
import Java.security.KeyManagementException;
import Java.net.URISyntaxException;
import Java.security.KeyStoreException;
import Java.security.UnrecoverableKeyException;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import Java.security.SecureRandom;
import org.Apache.http.client.HttpClient;
import org.Apache.http.impl.client.DefaultHttpClient;
import org.Apache.http.conn.ssl.SSLSocketFactory;
import org.Apache.http.conn.ClientConnectionManager;
import org.Apache.http.conn.scheme.Scheme;
import org.Apache.http.conn.scheme.SchemeRegistry;
import org.Apache.http.client.methods.HttpGet;
public class DataLoader {

    public HttpResponse secureLoadData(String url)
            throws ClientProtocolException, IOException,
            NoSuchAlgorithmException, KeyManagementException,
            URISyntaxException, KeyStoreException, UnrecoverableKeyException {
        SSLContext ctx = SSLContext.getInstance("TLS");
        ctx.init(null, new TrustManager[] { new CustomX509TrustManager() },
                new SecureRandom());

        HttpClient client = new DefaultHttpClient();

        SSLSocketFactory ssf = new CustomSSLSocketFactory(ctx);
        ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
        ClientConnectionManager ccm = client.getConnectionManager();
        SchemeRegistry sr = ccm.getSchemeRegistry();
        sr.register(new Scheme("https", ssf, 443));
        DefaultHttpClient sslClient = new DefaultHttpClient(ccm,
                client.getParams());

        HttpGet get = new HttpGet(new URI(url));
        HttpResponse response = sslClient.execute(get);

        return response;
    }

}
56
My-Name-Is

Wenn Sie das (Entwickler-) Zertifikat "Nicht vertrauenswürdig" verwenden, finden Sie nachfolgend die Lösung. Wir müssen allen Zertifikaten vertrauen, und unten ist der Weg, dies zu tun. Für vertrauenswürdige Zertifikate funktioniert es, ohne die unten aufgeführten Funktionen hinzuzufügen. Wir müssen lediglich http in https ändern und es wird funktionieren.

Hier ist die Lösung für nicht vertrauenswürdige Zertifikate.

In HttpClient-Weise sollten Sie eine benutzerdefinierte Klasse aus org.Apache.http.conn.ssl.SSLSocketFactory und nicht aus der org.Apache.http.conn.ssl.SSLSocketFactory selbst erstellen

beispiel ist wie ...

import Java.io.IOException;
import Java.net.Socket;
import Java.net.UnknownHostException;
import Java.security.KeyManagementException;
import Java.security.KeyStore;
import Java.security.KeyStoreException;
import Java.security.NoSuchAlgorithmException;
import Java.security.UnrecoverableKeyException;
import Java.security.cert.CertificateException;
import Java.security.cert.X509Certificate;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.Apache.http.conn.ssl.SSLSocketFactory;
public class MySSLSocketFactory extends SSLSocketFactory {
    SSLContext sslContext = SSLContext.getInstance("TLS");

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

        sslContext.init(null, new TrustManager[] { tm }, null);
    }

    @Override
    public Socket createSocket(Socket socket, String Host, int port, boolean autoClose) throws IOException, UnknownHostException {
        return sslContext.getSocketFactory().createSocket(socket, Host, port, autoClose);
    }

    @Override
    public Socket createSocket() throws IOException {
        return sslContext.getSocketFactory().createSocket();
    }
}

und verwenden Sie diese Klasse beim Erstellen einer Instanz von HttpClient.

public HttpClient getNewHttpClient() {
    try {
        KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
        trustStore.load(null, null);

        SSLSocketFactory sf = new MySSLSocketFactory(trustStore);
        sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

        HttpParams params = new BasicHttpParams();
        HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
        HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);

        SchemeRegistry registry = new SchemeRegistry();
        registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
        registry.register(new Scheme("https", sf, 443));

        ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry);

        return new DefaultHttpClient(ccm, params);
    } catch (Exception e) {
        return new DefaultHttpClient();
    }
}
14
santhosh

Überprüfen Sie das Datum Ihres Geräts. Sie haben es möglicherweise in ein anderes Jahr geändert. Ich bekomme ständig dieses Problem, wenn Kinder mein Telefon benutzen.

7
Kris Yu

Wenn Sie mit einem vertrauenswürdigen Zertifikat auf den Server zugreifen können, ist es eine viel bessere Lösung, das SSL korrekt zu konfigurieren, da Android ist in Bezug auf die SSL-Überprüfung stärker eingeschränkt als iOS- und Desktop-Browser

Diese Lösung erfordert keine Änderungen in Ihrer Android App, daher ist sie sauberer.

Hier ist ein Beispiel für eine SSL-Konfiguration für Apache (fügen Sie sie Ihrer VirtualHost-Definition hinzu, z. B./etc/Apache2/sites-enabled).

SSLEngine on
SSLCertificateFile    YOUR_CERT_PATH
SSLCACertificateFile  CA_ROOT_CERT_PATH
SSLCertificateKeyFile KEY_PATH

Ich hatte den gleichen Fehler und als ich das CA-Stammzertifikat hinzufügte, war der Fehler behoben und Android beschwerte sich nicht mehr. Geben Sie die korrekten Pfade für diese Dateien an, starten Sie Apache neu und testen Sie erneut.

Die Datei für das CA-Stammzertifikat kann sowohl das Stammzertifikat als auch das Zwischenzertifikat enthalten

Sie können Ihre SSL-Konfiguration mit this site testen und sicherstellen, dass im Ergebnis unter Certification Paths der Server alle sendet die erforderlichen Zertifikate.

3
iTech

Bei der Suche nach dieser Ausnahme erhalten Sie lediglich den Rat, "Alle Zertifikate zulassen" zu implementieren.

Das Javadoc für SSLPeerUnverifiedException besagt:

Wenn der Peer sich nicht identifizieren konnte (z. B. kein Zertifikat, die verwendete Cipher Suite unterstützt keine Authentifizierung oder es wurde keine Peer-Authentifizierung während des SSL-Handshakes eingerichtet), wird diese Ausnahme ausgelöst.

Der Fehler könnte also sein, dass die Verbindung so instabil ist und Anfragen viel Zeit in Anspruch nehmen. In unserer mobilen App treten manchmal viele Verbindungs-/Socket-Timeouts in Kombination mit dieser SSLPeerUnverifiedException auf. Einige Anfragen kommen durch, aber es dauert 60s + - die Netzwerkverbindung ist in diesen Fällen einfach unerträglich.

In solchen Fällen ist es nicht ratsam, dies mit der Option "Alle Zertifikate zulassen" zu erzwingen, sondern eine geeignete Strategie für den erneuten Versuch zu implementieren.

1
icyerasor

Ermöglichen Sie dem Android-Sicherheitsanbieter das Update, wenn Sie Ihre App starten.

Der Standardanbieter vor 5.0+ deaktiviert SSLv3 nicht. Vorausgesetzt, Sie haben Zugriff auf Google Play-Dienste, ist es relativ einfach, den Android-Sicherheitsanbieter von Ihrer App aus zu patchen.

  private void updateAndroidSecurityProvider(Activity callingActivity) {
    try {
        ProviderInstaller.installIfNeeded(this);
    } catch (GooglePlayServicesRepairableException e) {
      // Thrown when Google Play Services is not installed, up-to-date, or  enabled
        // Show dialog to allow users to install, update, or otherwise    enable Google Play services.
       GooglePlayServicesUtil.getErrorDialog(e.getConnectionStatusCode(), callingActivity, 0);
    } catch (GooglePlayServicesNotAvailableException e) {
        Log.e("SecurityException", "Google Play Services not available.");
    }
}

Quelle: Patch des Sicherheitsanbieters mit ProviderInstaller Provider

1
nani