开发者

HTTPS and self-signed certificate issue

I have to use HTTPS for sending POST requests to a server (using a self-signed certificate). This is how I do it:

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

With getHttpClient() defined as follows:

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 manage开发者_运维问答r
    ThreadSafeClientConnManager manager = new ThreadSafeClientConnManager(params, registry);

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

    return client;

}

But I get a "Not trusted server certificate" exception. I know several questions about self-signed certificates have already been posted here, but none of them worked for me...

Does anyone know how to do?

Some details: I'm working with API level 4 (Android 1.6) on emulator.


I finally solved it, using a custom subclass of 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();
    }

}

And I use it as follows:

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;

}

Don't know why the other solutions I found did not work for me...


for self documenting and to help others resolve the imports on accepted the answers (which works for me but spend time testing the imports between java., javax. and 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;


try this before performing the request

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜