2011-05-10 38 views
6

Tengo que usar HTTPS para enviar solicitudes POST a un servidor (utilizando un certificado autofirmado). Así es como lo hago:HTTPS y emisión de certificado autofirmado

HttpClient httpClient = getHttpClient(); 

for (int i = 0; i < PARAMS.length && !mHttpPost.isAborted(); ++i) { 
    mHttpPost.setURI(URI.create(mUri + "/" + PARAMS[i].getPath())); 
    mHttpPost.setEntity(new UrlEncodedFormEntity(PARAMS[i].getContents(), HTTP.UTF_8)); 
    HttpResponse response = httpClient.execute(mHttpPost); 
    [...] 
} 

Con getHttpClient() se define de la siguiente manera:

public static DefaultHttpClient getHttpClient() { 

    DefaultHttpClient client = null; 

    // Setting up parameters 
    HttpParams params = new BasicHttpParams(); 
    HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1); 
    HttpProtocolParams.setContentCharset(params, "utf-8"); 
    params.setBooleanParameter("http.protocol.expect-continue", false); 

    // Setting timeout 
    HttpConnectionParams.setConnectionTimeout(params, TIMEOUT); 
    HttpConnectionParams.setSoTimeout(params, TIMEOUT); 

    // Registering schemes for both HTTP and HTTPS 
    SchemeRegistry registry = new SchemeRegistry(); 
    registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80)); 
    final SSLSocketFactory sslSocketFactory = SSLSocketFactory.getSocketFactory(); 
    sslSocketFactory.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); 
    registry.register(new Scheme("https", sslSocketFactory, 443)); 

    // Creating thread safe client connection manager 
    ThreadSafeClientConnManager manager = new ThreadSafeClientConnManager(params, registry); 

    // Creating HTTP client 
    client = new DefaultHttpClient(manager, params); 

    return client; 

} 

pero me da un "Certificado no seguro servidor" excepción. Sé que ya se han publicado varias preguntas sobre los certificados autofirmados, pero ninguno funcionó para mí ...

¿Alguien sabe cómo hacerlo?

Algunos detalles: Estoy trabajando con API nivel 4 (Android 1.6) en emulador.

Respuesta

13

finalmente lo resolví, utilizando una subclase personalizada de SSLSocketFactory:

public class CustomSSLSocketFactory extends SSLSocketFactory { 

    private SSLContext sslContext = SSLContext.getInstance("TLS"); 

    public CustomSSLSocketFactory(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 lo uso de la siguiente manera:

public HttpClient getHttpClient() { 

    DefaultHttpClient client = null; 

    try { 

     KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); 
     trustStore.load(null, null); 

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

     // Setting up parameters 
     HttpParams params = new BasicHttpParams(); 
     HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1); 
     HttpProtocolParams.setContentCharset(params, "utf-8"); 
     params.setBooleanParameter("http.protocol.expect-continue", false); 

     // Setting timeout 
     HttpConnectionParams.setConnectionTimeout(params, TIMEOUT); 
     HttpConnectionParams.setSoTimeout(params, TIMEOUT); 

     // Registering schemes for both HTTP and HTTPS 
     SchemeRegistry registry = new SchemeRegistry(); 
     registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80)); 
     registry.register(new Scheme("https", sf, 443)); 

     // Creating thread safe client connection manager 
     ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry); 

     // Creating HTTP client 
     client = new DefaultHttpClient(ccm, params); 

     // Registering user name and password for authentication 
     client.getCredentialsProvider().setCredentials(
       new AuthScope(null, -1), 
       new UsernamePasswordCredentials(mUsername, mPassword)); 

    } catch (Exception e) { 
     client = new DefaultHttpClient(); 
    } 

    return client; 

} 

No sé por qué las otras soluciones que encontré no funcionaron para mí ...

+2

Hola, sé que esto es un post hace mucho tiempo. Pero actualmente estoy atascado con esta conexión HTTPS. ¿Cuáles son los pasos que debo hacer antes de poder pasar en cualquier sitio seguro HTTPS? –

+1

Esta solución es realmente peligrosa; está descartando los beneficios de seguridad de usar HTTPS (su código confiará ciegamente en certificados incorrectos). – Brian

0

probar esto antes de realizar la solicitud

SSLSocketFactory ssl = (SSLSocketFactory)http.getConnectionManager().getSchemeRegistry().getScheme("https").getSocketFactory(); 
    ssl.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); 
+0

lo siento, lo estás haciendo alreay que de una manera similar, pero funciona para mí ... – 2red13

6

para auto-documentar y para ayudar a otros a resolver las importaciones en las respuestas aceptadas (lo cual funciona para mí, pero dedique tiempo a probar las importaciones entre java). , javax. y org.apache.http *):.

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.HttpVersion; 
import org.apache.http.client.HttpClient; 
import org.apache.http.conn.ClientConnectionManager; 
import org.apache.http.conn.scheme.PlainSocketFactory; 
import org.apache.http.conn.scheme.Scheme; 
import org.apache.http.conn.scheme.SchemeRegistry; 
import org.apache.http.conn.ssl.SSLSocketFactory; 
import org.apache.http.impl.client.DefaultHttpClient; 
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager; 
import org.apache.http.params.BasicHttpParams; 
import org.apache.http.params.HttpConnectionParams; 
import org.apache.http.params.HttpParams; 
import org.apache.http.params.HttpProtocolParams; 
Cuestiones relacionadas