java android chrome://flags/#enable-quic - Errore SSL SSL HttpGet (nessun certificato peer) Errore OR (Connessione chiusa da peer)





3 Answers

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

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.




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






Related