java - Android:如何使用自签名证书和 SSL 缓存创建 HttpClient

标签 java android caching ssl httpclient

我在实现与 Android 的 SSL 连接时遇到了一些麻烦。我的程序在特定的时间间隔内发送数据。为了减少发送的数据量,我想使用 SSL 缓存。 有人知道如何在 Android 中使用自签名证书和 SSL 缓存创建 HttpClient 吗?

我想使用 HttpClient 类,我的解决方案如下所示(以 CastException 结尾):

private HttpClient getNewHttpClient(Context context, InputStream sslCertificate) {
        SSLSessionCache sslSessionCache = new SSLSessionCache(context);
        SSLCertificateSocketFactory socketFactory = (SSLCertificateSocketFactory) SSLCertificateSocketFactory.getDefault(15000, sslSessionCache);

        KeyStore keyStore = getSSLKeyStore(sslCertificate);           
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        tmf.init(keyStore);

        socketFactory.setTrustManagers(tmf.getTrustManagers());                   

        HttpParams connectionParameters = new BasicHttpParams();
        HttpProtocolParams.setVersion(connectionParameters , HttpVersion.HTTP_1_1);
        HttpProtocolParams.setContentCharset(connectionParameters , HTTP.UTF_8);
        HttpConnectionParams.setStaleCheckingEnabled(connectionParameters , false);
        HttpConnectionParams.setConnectionTimeout(connectionParameters , 4 * 1000);
        HttpConnectionParams.setSoTimeout(connectionParameters , 5 * 1000);
        HttpConnectionParams.setSocketBufferSize(connectionParameters , 8192);
        HttpClientParams.setRedirecting(connectionParameters , false);

        SchemeRegistry registry = new SchemeRegistry();     

        registry.register(new Scheme("https",  (SocketFactory) socketFactory , 443));
        ClientConnectionManager connectionManager = new ThreadSafeClientConnManager(connectionParameters, registry);

        HttpClient httpClient = new DefaultHttpClient(connectionManager, connectionParameters);

        return httpClient;
}

这是在将新构建方案注册到 SchemeRegistry 时的 CastException

 W/System.err(343): java.lang.ClassCastException: org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl cannot be cast to org.apache.http.conn.scheme.SocketFactory

最佳答案

    public class SimpleSSLSocketFactory extends
    org.apache.http.conn.ssl.SSLSocketFactory {
private javax.net.ssl.SSLSocketFactory sslFactory = HttpsURLConnection
        .getDefaultSSLSocketFactory();

public SimpleSSLSocketFactory(KeyStore truststore)
        throws NoSuchAlgorithmException, KeyManagementException,
        KeyStoreException, UnrecoverableKeyException {
    super(null);
    try {
        SSLContext context = SSLContext.getInstance("TLS");
        TrustManager[] trustAllCerts = new TrustManager[] { new  

                 X509TrustManager() {
            public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                return new java.security.cert.X509Certificate[] {};
            }
            public void checkClientTrusted(X509Certificate[] chain,
                    String authType) throws CertificateException {
            }

            public void checkServerTrusted(X509Certificate[] chain,
                    String authType) throws CertificateException {
            }
        } };

        // Initialize the socket factory
        context.init(null, trustAllCerts, new SecureRandom());
        sslFactory = context.getSocketFactory();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

@Override
public Socket createSocket(Socket socket, String host, int port,
        boolean autoClose) throws IOException, UnknownHostException {
    return sslFactory.createSocket(socket, host, port, autoClose);
}

@Override
public Socket createSocket() throws IOException {
    return sslFactory.createSocket();
}

   U can call like this 


                  try {
        SSLSocketFactory sslFactory = new SimpleSSLSocketFactory(null);
        sslFactory
                .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", sslFactory, 443));
        ClientConnectionManager ccm = new ThreadSafeClientConnManager(
                params, registry);
        DefaultHttpClient httpClient = new DefaultHttpClient(ccm, params);
        HttpPost httpPost = new HttpPost(url);
        HttpHost proxy = new HttpHost("50.104.5.277", 23333);

        //httpPost.setHeader("Content-Type", "text/xml");
        httpPost.setEntity(entity);
        httpClient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY,
                proxy);
        HttpResponse httpResponse = httpClient.execute(httpPost);
        HttpEntity httpEntity = httpResponse.getEntity();
        output = EntityUtils.toString(httpEntity);

        // Toast.makeText(getApplicationContext(), xml, 1000).show();
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    } catch (ClientProtocolException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } catch (KeyManagementException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (UnrecoverableKeyException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (NoSuchAlgorithmException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (KeyStoreException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    return output;
}

关于java - Android:如何使用自签名证书和 SSL 缓存创建 HttpClient,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18658075/

相关文章:

java - 每个路径 Spring 多个 HandlerMethodArgumentResolver

java - 扫描仪需要/正在请求输入两次

android - 如何在 Android 中为用户的日历创建或添加不可编辑的事件?

Android:为什么应用程序 RAM 内存不断增长?

java - JedisPoolConfig 不可分配给 GenericObjectPoolConfig

java - 具有可调整数组大小的 toString 方法

java - JSoup 如何获取所有回复

java - 修复 Google API task-android-sample 的内存不足错误

java - 客户端缓存的空间限制

php - 警告 : fopen() [function. fopen]:文件名不能为空