ENGLISH 4006-967-446
首页>最新数字证书问答>android httpClient 支持HTTPS的访问方式

android httpClient 支持HTTPS的访问方式

最近项目需要用到httpClient走HTTPS的访问方式进行数据传输,在度娘与谷哥大神的帮助下,结论出了以下做法,提出来给需要的人,技术上就不多说了自己查了

环境:android 4.4 api 19

帮助

1.创建class

importorg.apache.http.HttpVersion;

importorg.apache.http.conn.ClientConnectionManager;

importorg.apache.http.conn.params.ConnManagerPNames;

importorg.apache.http.conn.params.ConnPerRouteBean;

importorg.apache.http.conn.scheme.PlainSocketFactory;

importorg.apache.http.conn.scheme.Scheme;

importorg.apache.http.conn.scheme.SchemeRegistry;

importorg.apache.http.conn.ssl.SSLSocketFactory;

importorg.apache.http.impl.client.DefaultHttpClient;

importorg.apache.http.impl.conn.SingleClientConnManager;

importorg.apache.http.params.BasicHttpParams;

importorg.apache.http.params.HttpConnectionParams;

importorg.apache.http.params.HttpParams;

importorg.apache.http.params.HttpProtocolParams;

importorg.apache.http.protocol.HTTP;

 

importjava.io.IOException;

importjava.net.Socket;

importjava.net.UnknownHostException;

importjava.security.KeyManagementException;

importjava.security.KeyStore;

importjava.security.KeyStoreException;

importjava.security.NoSuchAlgorithmException;

importjava.security.UnrecoverableKeyException;

importjava.security.cert.X509Certificate;

 

importjavax.net.ssl.SSLContext;

importjavax.net.ssl.SSLSocket;

importjavax.net.ssl.TrustManager;

importjavax.net.ssl.X509TrustManager;

 

publicclass SSLSocketFactoryEx extends SSLSocketFactory {

    public final static int TIME_OUT_DELAY =20000;

 

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

 

    public SSLSocketFactoryEx(KeyStoretruststore)

            throws NoSuchAlgorithmException,KeyManagementException,

            KeyStoreException,UnrecoverableKeyException {

        super(truststore);

        initSSLContext();

    }

 

    TrustManager tm = new X509TrustManager() {

        @Override

        public X509Certificate[]getAcceptedIssuers() {

            // TODO Auto-generated method stub

            return null;

        }

        @Override

        public void checkClientTrusted(

                java.security.cert.X509Certificate[]chain, String authType)

                throwsjava.security.cert.CertificateException {}

        @Override

        public void checkServerTrusted(

               java.security.cert.X509Certificate[] chain, String authType)

                throwsjava.security.cert.CertificateException {}

    };

 

    @Override

    public Socket createSocket(Socket socket,String host, int port, boolean autoClose) throws IOException,UnknownHostException {

        SSLSocket sslSocket=(SSLSocket)sslContext.getSocketFactory().createSocket(socket, host, port, autoClose);

        sslSocket.setEnabledProtocols(newString[]{"TLSv1.2"});

        return sslSocket;

    }

 

    private void initSSLContext() {

        try {

            // 既然是跳过认证,我们把没有的都填null,此时发现第二个参数是一个数组,那么意思就是我们可以放多个证书认证;

            sslContext.init(null, newTrustManager[] { tm }, null);

        } catch (KeyManagementException e) {

            // TODO Auto-generated catch block

            e.printStackTrace();

        }

    }

 

    public static DefaultHttpClientgetNewHttpClient() {

        try {

            // 查看API这里可以得到一个默认的Type.

            KeyStore truststore =KeyStore.getInstance(KeyStore

                    .getDefaultType());

            truststore.load(null, null);

            // 这里发现需要一个KeyStore,那么我们就在上面New一个KeyStore,这是一个密钥库,查看API发现能直接getInstance得到对象;

            SSLSocketFactory factory = newSSLSocketFactoryEx(truststore);

            // 这里就是我们最需要的也是最关键的一步,设置主机认证,通过API发现有一个常量就是允许所有认证通过。

           factory.setHostnameVerifier(ALLOW_ALL_HOSTNAME_VERIFIER);

 

            // 实现Httpprams的子类

            HttpParams params = newBasicHttpParams();

            params.setParameter(ConnManagerPNames.MAX_TOTAL_CONNECTIONS,30);

           params.setParameter(ConnManagerPNames.MAX_CONNECTIONS_PER_ROUTE, newConnPerRouteBean(30));

           params.setParameter(HttpProtocolParams.USE_EXPECT_CONTINUE, false);

            //通过Http适配器设置必要参数,现在通用HTTP1.1协议,和UTF-8字符。

           HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);

           HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);

            //通过适配器设置连接参数,等待时间和,连接时间

           HttpConnectionParams.setSoTimeout(params, TIME_OUT_DELAY);

           HttpConnectionParams.setConnectionTimeout(params, TIME_OUT_DELAY);

 

            // 同样New出来,查看API,需要我们注册一个计划,来封装协议细节

            SchemeRegistry schreg = newSchemeRegistry();

            // 最后一个参数是端口设置,Https常用的端口就是443。

            schreg.register(newScheme("https", factory, 443));

            // 既然是工具类,这里也把http协议加上,中间的协议工厂我们就用简单的PlainSocketFactory,这里可以通过API查看到,端口就用常用的80端口(默认)

            schreg.register(newScheme("http", PlainSocketFactory.getSocketFactory(), 80));

 

            // ClientConnectionManager是一个借口,就实现他的子类,同样需要2个参数,第一个我们熟悉,第二个就是让我们自定义自己的一套方案协议,继续在上面一步一步完成;

            ClientConnectionManager conman =new SingleClientConnManager(

                    params, schreg);

 

            // 返回我们需要的一个默认Httpclient,为了把之前做的关联起来,就new最多参数的构造函数,需要2个参数,Httpparams是我们熟悉的,

            // 发现ClientConnectionManager不太熟悉,通过API发现这是客服端连接管理者,既然这样,就在上面一步一步完成。

            return newDefaultHttpClient(conman, params);

        } catch (Exception e) {

            // TODO: handle exception

        }

        return new DefaultHttpClient();

    }

 

}

2.应用上

            //for https

            HttpClient httpClient =SSLSocketFactoryEx.getNewHttpClient();

            //設定參數

           httpClient.getParams().setIntParameter(HttpConnectionParams.SO_TIMEOUT,TIME_OUT_DELAY);

           httpClient.getParams().setIntParameter(HttpConnectionParams.CONNECTION_TIMEOUT,TIME_OUT_DELAY);

            HttpPost httpPost = new HttpPost(EndpointURL);

            //添加http头信息

            httpPost.addHeader("xxx...",xxx...);

           //json數據

            StringEntitystringEntity = new StringEntity(jsonString);

           stringEntity.setContentType("application/json;charset=UTF-8");

            stringEntity.setContentEncoding(newBasicHeader(HTTP.CONTENT_TYPE,"application/json;charset=UTF-8"));

            httpPost.setEntity(stringEntity);

           //回傳服務查詢結果(json)

            httpResponse =httpClient.execute(httpPost);

 

本文转自CSDN博客