java potrebbe - Errore SSL SSL HttpGet (nessun certificato peer) Errore OR (Connessione chiusa da peer)





di pagina (7)


Controlla la data del tuo dispositivo. Potresti averlo cambiato in un altro anno. Ottengo costantemente questo problema quando i bambini usano il mio telefono.

Sto cercando di fare un semplice HttpGet per leggere una pagina web. Ho questo lavoro su iOS e lavorando su Android su http, ma non su https.

L'url è un IP di rete interno e una porta personalizzata, quindi posso leggere con http come questo utilizzando un percorso http://ipaddress:port/MyPage.html

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;

Quando provo a usare https, ottengo l'errore del No peer certificate . Così ho provato a utilizzare questo codice: 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();
        }
    }

ma questo mi dà una Connection closed by peer errore Connection closed by peer .

Che cosa sto facendo di sbagliato? Posso tranquillamente ignorare il certificato, dato che si tratta di una rete interna con certificato autofirmato, tuttavia non ho il controllo sulla vert e gli utenti della mia app possono avere certs diversi, quindi ho davvero bisogno di accettarlo o bypassarlo automaticamente.

Grazie

MODIFICARE ------------------------------

Dopo aver provato il mio nome-è la risposta qui sotto: Ho creato una classe CustomX509TrustManager come suggerito, quindi creo un HttpClient personalizzato usandolo in questo modo:

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

E finalmente usa questo HttpClient in questo modo:

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;

Il percorso registrato è nel formato https://ipaddress:8080/Page.html Ma ottengo un errore di Connection closed By Peer :

05-24 08: 20: 32.500: E / ConnectionHelper (1129): IOException 05-24 08: 20: 32.550: E / ConnectionHelper (1129): contenuto di caricamento Eccezione 05-24 08: 20: 32.550: E / ConnectionHelper (1129 ): javax.net.ssl.SSLException: Connessione chiusa dal peer 05-24 08: 20: 32.550: E / ConnectionHelper (1129): su org.apache.harmony.xnet.provider.jsse.NativeCrypto.SSL_do_handshake (metodo nativo) 05-24 08: 20: 32.550: E / ConnectionHelper (1129): su org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake (OpenSSLSocketImpl.java:410) 05-24 08: 20: 32.550: E / ConnectionHelper (1129): all'indirizzo org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl $ SSLInputStream. (OpenSSLSocketImpl.java:643) 05-24 08: 20: 32.550: E / ConnectionHelper (1129): su org.apache. harmony.xnet.provider.jsse.OpenSSLSocketImpl.getInputStream (OpenSSLSocketImpl.java:614) 05-24 08: 20: 32.550: E / ConnectionHelper (1129): all'indirizzo org.apache.http.impl.io.SocketInputBuffer. (SocketInputBuffer. java: 70) 05-24 08: 20: 32.550: E / ConnectionHelper (1129): su org.apache.http.impl.Soc ketHttpClientConnection.createSessionInputBuffer (SocketHttpClientConnection.java:83) 05-24 08: 20: 32.550: E / ConnectionHelper (1129): su org.apache.http.impl.conn.DefaultClientConnection.createSessionInputBuffer (DefaultClientConnection.java:170) 05-24 08: 20: 32.550: E / ConnectionHelper (1129): su org.apache.http.impl.SocketHttpClientConnection.bind (SocketHttpClientConnection.java:106) 05-24 08: 20: 32.550: E / ConnectionHelper (1129): su org .apache.http.impl.conn.DefaultClientConnection.openCompleted (DefaultClientConnection.java:129) 05-24 08: 20: 32.550: E / ConnectionHelper (1129): su org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection ( DefaultClientConnectionOperator.java:172) 05-24 08: 20: 32.550: E / ConnectionHelper (1129): su org.apache.http.impl.conn.AbstractPoolEntry.open (AbstractPoolEntry.java:164) 05-24 08:20: 32.550: E / ConnectionHelper (1129): su org.apache.http.impl.conn.AbstractPooledConnAdapter.open (AbstractPooledConnAdapter.java:119) 05-24 08: 20: 32.550: E / ConnectionHelper ( 1129): su org.apache.http.impl.client.DefaultRequestDirector.execute (DefaultRequestDirector.java:360) 05-24 08: 20: 32.550: E / ConnectionHelper (1129): su org.apache.http.impl.client .AbstractHttpClient.execute (AbstractHttpClient.java:555) 05-24 08: 20: 32.550: E / ConnectionHelper (1129): su org.apache.http.impl.client.AbstractHttpClient.execute (AbstractHttpClient.java:487) 05- 24 08: 20: 32.550: E / ConnectionHelper (1129): su org.apache.http.impl.client.AbstractHttpClient.execute (AbstractHttpClient.java:465) 05-24 08: 20: 32.550: E / ConnectionHelper (1129) : su com.d_apps.my_app.connection_helpers.ConnectionHelper $ httpGETTask.doInBackground (ConnectionHelper.java:114)




Se si ha accesso al server con un certificato attendibile, una soluzione molto migliore è quella di configurare correttamente l'SSL perché Android è più limitato rispetto al browser iOS e desktop per quanto riguarda la verifica SSL

Questa soluzione non richiede alcuna modifica nella tua app Android, quindi è più pulita.

Ecco un esempio di configurazione SSL per apache (aggiungilo alla tua definizione di VirtualHost es. / Etc / apache2 / sites-enabled)

SSLEngine on
SSLCertificateFile    YOUR_CERT_PATH
SSLCACertificateFile  CA_ROOT_CERT_PATH
SSLCertificateKeyFile KEY_PATH

Ho avuto lo stesso errore e quando ho aggiunto il certificato di root CA, l'errore è andato e Android non si è più lamentato. Fornisci i percorsi corretti per questi file, riavvia Apache e prova di nuovo.

Il file per il certificato radice CA può contenere sia il certificato radice che quello intermedio

È possibile verificare la configurazione SSL con questo sito e assicurarsi che nel risultato in Percorsi di certificazione il server invii tutti i certificati richiesti.




Inizialmente utilizzavo HttpsURLConnection ma non funzionava in modo coerente, quindi ho deciso di utilizzare HttpClient . Ora funziona.




Consenti al provider di sicurezza di Android di aggiornarsi quando avvii la tua app.

Il provider predefinito prima di 5.0+ non disabilita SSLv3. Se hai accesso ai servizi di Google Play, è relativamente semplice applicare la patch del provider di sicurezza di Android dalla tua app.

  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.");
    }
}

Fonte: applicazione di patch al provider di sicurezza con ProviderInstaller Provider




La seguente fonte dovrebbe risolvere il tuo problema.

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

}



Se si utilizza il certificato "Non attendibile" (sviluppatore), di seguito è riportata la soluzione. Abbiamo bisogno di fiducia in tutti i certificati, e di seguito è il modo per farlo. Per i certificati affidabili funziona senza aggiungere funzionalità di sotto, abbiamo solo bisogno di cambiare http in https e funzionerà.

Ecco la soluzione per il certificato non attendibile.

In modo HttpClient, dovresti creare una classe personalizzata da org.apache.http.conn.ssl.SSLSocketFactory, non da quella org.apache.http.conn.ssl.SSLSocketFactory stessa

esempio è come ...

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

e utilizzare questa classe durante la creazione dell'istanza di 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();
    }
}







java android ssl https httpclient