matemáticas homólogo homología homologos homologo geometria elementos java android ssl https httpclient

java - homología - Error de Android SSL HttpGet(sin certificado de homólogo) O error de(conexión cerrada por homólogo)



homologo geometria (7)

Estoy tratando de hacer un simple HttpGet para leer una página web. Tengo esto trabajando en iOS y trabajando en Android a través de http, pero no en https.

La url es una red interna IP y puerto personalizado, por lo que puedo leer con http como este usando una ruta de acceso de 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;

Cuando intento usar https, obtengo el error de No peer certificate . Así que he intentado utilizar este código: 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(); } }

pero esto me da una Connection closed by peer error Connection closed by peer .

¿Qué estoy haciendo mal? Puedo ignorar el certificado de forma segura, ya que es una red interna con certificado autofirmado, sin embargo, no tengo control sobre el vert y los usuarios de mi aplicación pueden tener diferentes certs, así que realmente necesito aceptarlo automáticamente o pasarlo por alto.

Gracias

EDITAR ------------------------------

Después de intentar la respuesta de Mi-Nombre-Es a continuación: He creado una clase CustomX509TrustManager como se sugiere, luego creo un HttpClient personalizado usándolo así:

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

Y finalmente usa este HttpClient así:

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;

La ruta de acceso registrada está en el formato https://ipaddress:8080/Page.html Pero obtengo una Connection closed By Peer error de grupo:

05-24 08: 20: 32.500: E / ConnectionHelper (1129): IOException 05-24 08: 20: 32.550: E / ConnectionHelper (1129): Excepción de carga de contenidos 05-24 08: 20: 32.550: E / ConnectionHelper (1129 ): javax.net.ssl.SSLException: conexión cerrada por pares 05-24 08: 20: 32.550: E / ConnectionHelper (1129): en org.apache.harmony.xnet.provider.jsse.NativeCrypto.SSL_do_handshake (método nativo) 05-24 08: 20: 32.550: E / ConnectionHelper (1129): en org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake (OpenSSLSocketImpl.java:410) 05-24 08: 20: 32.550: E / ConnectionHelper (1129): en org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl $ SSLInputStream. (OpenSSLSocketImpl.java:643) 05-24 08: 20: 32.550: E / ConnectionHelper (1129): en org.apache. harmony.xnet.provider.jsse.OpenSSLSocketImpl.getInputStream (OpenSSLSocketImpl.java:614) 05-24 08: 20: 32.550: E / ConnectionHelper (1129): en org.apache.http.impl.io.SocketInputBuffer. (SocketInputBuffer. java: 70) 05-24 08: 20: 32.550: E / ConnectionHelper (1129): en org.apache.http.impl.Soc ketHttpClientConnection.createSessionInputBuffer (SocketHttpClientConnection.java:83) 05-24 08: 20: 32.550: E / ConnectionHelper (1129): en org.apache.http.impl.conn.DefaultClientConnection.createSessionInputBuffer (DefaultClientConnection.java:170) 05-24 08: 20: 32.550: E / ConnectionHelper (1129): en org.apache.http.impl.SocketHttpClientConnection.bind (SocketHttpClientConnection.java:106) 05-24 08: 20: 32.550: E / ConnectionHelper (1129): en org .apache.http.impl.conn.DefaultClientConnection.openCompleted (DefaultClientConnection.java:129) 05-24 08: 20: 32.550: E / ConnectionHelper (1129): en org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection ( DefaultClientConnectionOperator.java:172) 05-24 08: 20: 32.550: E / ConnectionHelper (1129): en org.apache.http.impl.conn.AbstractPoolEntry.open (AbstractPoolEntry.java:164) 05-24 08:20: 32.550: E / ConnectionHelper (1129): en org.apache.http.impl.conn.AbstractPooledConnAdapter.open (AbstractPooledConnAdapter.java:119) 05-24 08: 20: 32.550: E / ConnectionHelper ( 1129): en org.apache.http.impl.client.DefaultRequestDirector.execute (DefaultRequestDirector.java:360) 05-24 08: 20: 32.550: E / ConnectionHelper (1129): en org.apache.http.impl.client .AbstractHttpClient.execute (AbstractHttpClient.java:555) 05-24 08: 20: 32.550: E / ConnectionHelper (1129): en org.apache.http.impl.client.AbstractHttpClient.execute (AbstractHttpClient.java:487) 05- 24 08: 20: 32.550: E / ConnectionHelper (1129): en org.apache.http.impl.client.AbstractHttpClient.execute (AbstractHttpClient.java:465) 05-24 08: 20: 32.550: E / ConnectionHelper (1129) : en com.d_apps.my_app.connection_helpers.ConnectionHelper $ httpGETTask.doInBackground (ConnectionHelper.java:114)


Al buscar esta excepción, todo lo que obtiene es el consejo de implementar "permitir todos los certs".

El javadoc para estados SSLPeerUnverifiedException:

Cuando el par no pudo identificarse (por ejemplo, ningún certificado, el conjunto de cifrado particular que se usa no admite la autenticación, o no se estableció la autenticación entre pares durante el protocolo de enlace SSL) se lanza esta excepción.

Entonces, el error podría ser que la conexión es tan escamosa / inestable y las solicitudes tardan cantidades ridículas. En nuestra aplicación móvil, a veces experimentamos muchas conexiones / Socket-Timeouts en combinación con estas SSLPeerUnverifiedException. Algunas solicitudes se procesan pero toman 60s + - la conexión de red simplemente apesta más allá de todos los medios en estos casos.

Simplemente forzar esto brutalmente con "permitir todos los certs" no es recomendable en tales casos, sino implementar una estrategia de reintento adecuada.


La siguiente fuente debería solucionar su 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; } }


Originalmente estaba usando HttpsURLConnection pero no funcionaba de manera consistente, así que decidí usar HttpClient . Ahora funciona.


Permita que el proveedor de seguridad de Android se actualice al iniciar su aplicación.

El proveedor predeterminado antes de 5.0+ no deshabilita SSLv3. Siempre que tenga acceso a los servicios de Google Play, es relativamente sencillo parchear el proveedor de seguridad de Android desde su aplicación.

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

Fuente: aplicación de parches al proveedor de seguridad con ProviderInstaller Provider


Si está utilizando el certificado "No confiable" (desarrollador), a continuación encontrará la solución. Necesitamos confiar en todos los certificados, y abajo está la manera de hacerlo. Para los certificados confiables, funciona sin agregar la funcionalidad siguiente, solo tenemos que cambiar http a https y funcionará.

Aquí está la solución para el certificado no confiable.

En modo HttpClient, debe crear una clase personalizada de org.apache.http.conn.ssl.SSLSocketFactory, no la de una org.apache.http.conn.ssl.SSLSocketFactory en sí misma

ejemplo es como ...

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

y use esta clase mientras crea la instancia de 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(); } }


Si tiene acceso al servidor con un certificado de confianza, una solución mucho mejor es configurar correctamente el SSL porque Android está más restringido que el iOS y el navegador de escritorio con respecto a la verificación de SSL.

Esta solución no requiere ningún cambio en su aplicación de Android, por lo que es más limpio.

Aquí hay un ejemplo de configuración de SSL para apache (agréguela a su definición de VirtualHost, por ejemplo, / etc / apache2 / sites-enabled)

SSLEngine on SSLCertificateFile YOUR_CERT_PATH SSLCACertificateFile CA_ROOT_CERT_PATH SSLCertificateKeyFile KEY_PATH

Tuve el mismo error y cuando agregué el certificado raíz de CA, el error desapareció y android ya no se quejó. Proporcione las rutas correctas para estos archivos, reinicie Apache y vuelva a probar.

El archivo para el certificado raíz de CA puede contener tanto el certificado raíz como el certificado intermedio

Puede probar su configuración de SSL con este sitio y asegurarse de que en el resultado en Rutas de certificación el servidor envíe todos los certificados necesarios.


Verifique la fecha de su dispositivo. Puede haberlo cambiado a un año diferente. Consigo este problema constantemente cuando los niños usan mi teléfono.