versión verified una type studio servidor protocolo network enabled conjunto conexion común cliente cifrado check certificado admiten android ssl certificate httpclient

android - verified - retrofit ssl pinning



httpclient ssl certificate en android (3)

Tengo algunos problemas con SSL utilizando httpclient en Android. Estoy intentando acceder al certificado autofirmado en detalles. Deseo que mi aplicación confíe en todos los certificados (usaré SSL solo para el cifrado de datos). Primero intenté usar esta guía http://hc.apache.org/httpclient-3.x/sslguide.html en el escritorio funciona bien, pero en android todavía tengo javax.net.ssl.SSLException: Certificado de servidor no confiable. Después de buscar en google, encontré otros ejemplos de cómo habilitar ssl.

http://groups.google.com/group/android-developers/browse_thread/thread/62d856cdcfa9f16e - Trabajando cuando uso URLConnection pero con HttpClient todavía tengo la excepción.

http://www.discursive.com/books/cjcook/reference/http-webdav-sect-self-signed.html - en el escritorio, el uso de jar de apache funciona, pero el uso de android incluido en las clases de SDK no puede hacer que funcione .

http://mail-archives.apache.org/mod_mbox/hc-httpclient-users/200808.mbox/%3C1218824624.6561.14.camel@ubuntu%3E - también obtienes la misma excepción

Entonces, ¿cómo puedo confiar en todos los certificados en Android usando HttpClient?


Si observa el código de DefaultHttpClient, se ve así:

@Override protected ClientConnectionManager createClientConnectionManager() { SchemeRegistry registry = new SchemeRegistry(); registry.register( new Scheme("http", PlainSocketFactory.getSocketFactory(), 80)); registry.register( new Scheme("https", SSLSocketFactory.getSocketFactory(), 443)); ClientConnectionManager connManager = null; HttpParams params = getParams(); ... }

Observe la asignación del esquema https a org.apache.http.conn.ssl.SSLSocketFactory.getSocketFactory ().

Puede crear una implementación personalizada para la interfaz org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory ( http://hc.apache.org/httpclient-3.x/apidocs/org/apache/commons/httpclient/protocol/SecureProtocolSocketFactory. html ) donde puede crear java.net.SSLSocket con un TrustManager personalizado que acepte todo el certificado.

Es posible que desee consultar JSSE para obtener más detalles en http://java.sun.com/j2se/1.4.2/docs/guide/security/jsse/JSSefGuide.html


La idea clave es utilizar un SSLSocketFactory personalizado que implemente LayeredSocketFactory. El socket personalizado no necesita HostNameVerifier.

private static final class TrustAllSSLSocketFactory implements LayeredSocketFactory { private static final TrustAllSSLSocketFactory DEFAULT_FACTORY = new TrustAllSSLSocketFactory(); public static TrustAllSSLSocketFactory getSocketFactory() { return DEFAULT_FACTORY; } private SSLContext sslcontext; private javax.net.ssl.SSLSocketFactory socketfactory; private TrustAllSSLSocketFactory() { super(); TrustManager[] tm = new TrustManager[] { new X509TrustManager() { @Override public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { // do nothing } @Override public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { // do nothing } @Override public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; } } }; try { this.sslcontext = SSLContext.getInstance(SSLSocketFactory.TLS); this.sslcontext.init(null, tm, new SecureRandom()); this.socketfactory = this.sslcontext.getSocketFactory(); } catch ( NoSuchAlgorithmException e ) { Log.e(LOG_TAG, "Failed to instantiate TrustAllSSLSocketFactory!", e); } catch ( KeyManagementException e ) { Log.e(LOG_TAG, "Failed to instantiate TrustAllSSLSocketFactory!", e); } } @Override public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException, UnknownHostException { SSLSocket sslSocket = (SSLSocket) this.socketfactory.createSocket( socket, host, port, autoClose); return sslSocket; } @Override public Socket connectSocket(Socket sock, String host, int port, InetAddress localAddress, int localPort, HttpParams params) throws IOException, UnknownHostException, ConnectTimeoutException { if ( host == null ) { throw new IllegalArgumentException( "Target host may not be null."); } if ( params == null ) { throw new IllegalArgumentException( "Parameters may not be null."); } SSLSocket sslsock = (SSLSocket) ( ( sock != null ) ? sock : createSocket() ); if ( ( localAddress != null ) || ( localPort > 0 ) ) { // we need to bind explicitly if ( localPort < 0 ) { localPort = 0; // indicates "any" } InetSocketAddress isa = new InetSocketAddress(localAddress, localPort); sslsock.bind(isa); } int connTimeout = HttpConnectionParams.getConnectionTimeout(params); int soTimeout = HttpConnectionParams.getSoTimeout(params); InetSocketAddress remoteAddress; remoteAddress = new InetSocketAddress(host, port); sslsock.connect(remoteAddress, connTimeout); sslsock.setSoTimeout(soTimeout); return sslsock; } @Override public Socket createSocket() throws IOException { // the cast makes sure that the factory is working as expected return (SSLSocket) this.socketfactory.createSocket(); } @Override public boolean isSecure(Socket sock) throws IllegalArgumentException { return true; } }

Luego puede continuar utilizando el SSLSocketFactory personalizado en el registro del esquema admitido.

private static final BasicHttpParams sHttpParams = new BasicHttpParams(); private static final SchemeRegistry sSupportedSchemes = new SchemeRegistry(); static { sHttpParams.setParameter("http.socket.timeout", READ_TIMEOUT); sHttpParams.setParameter("http.connection.timeout", CONNECT_TIMEOUT); sSupportedSchemes.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80)); sSupportedSchemes.register(new Scheme("https", TrustAllSSLSocketFactory.getSocketFactory(), 443)); }