Android--https请求

来源:互联网 发布:软考程序员科目有哪些 编辑:程序博客网 时间:2024/06/05 18:17

Android平台上经常有使用https的需求,对于https服务器使用的根证书是受信任的证书的话,实现https是非常简单的,直接用httpclient库就行了,与使用http几乎没有区别。大多数情况下,服务器所使用的根证书是自签名的,或者签名机构不在设备的信任证书列表中,这样使用httpclient进行https连接就会失败。解决这个问题的办法有两种,一是在发起https连接之前将服务器证书加到httpclient的信任证书列表中,这个相对来说比较复杂一些,很容易出错;另一种办法是让httpclient信任所有的服务器证书,这种办法相对来说简单很多,但安全性则差一些,

一、不验证证书get方式:
String https = "https://www.google.com.hk";  
       try{  
           SSLContext sc = SSLContext.getInstance("TLS");  
           sc.init(null, new TrustManager[]{new MyTrustManager()}, new SecureRandom());  
           HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());  
           HttpsURLConnection.setDefaultHostnameVerifier(new MyHostnameVerifier());  
           HttpsURLConnection conn = (HttpsURLConnection)new URL(https).openConnection();  

标*****号开始至*****结束的一堆设置可不要

*****

http.setConnectTimeout(5 * 1000);
http.setRequestMethod("GET");
http.setRequestProperty("Accept", "image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/xaml+xml, application/vnd.ms-xpsdocument, application/x-ms-xbap, application/x-ms-application, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*");
http.setRequestProperty("Accept-Language", "zh-CN");
http.setRequestProperty("Referer", downUrl.toString()); 
http.setRequestProperty("Charset", "UTF-8");
int startPos = block * (threadId - 1) + downLength;//开始位置
// int endPos = block * threadId -1;//结束位置
int endPos = block;//只有一个线程
http.setRequestProperty("Range", "bytes=" + startPos + "-"+ endPos);//设置获取实体数据的范围
http.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.2; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)");
http.setRequestProperty("Connection", "Keep-Alive");

*****
           conn.setDoOutput(true);  
           conn.setDoInput(true);  
           conn.connect();  
           BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));   
           StringBuffer sb = new StringBuffer();   
           String line;   
           while ((line = br.readLine()) != null)   
               sb.append(line);                  
           System.out.println(sb.toString());  
          }catch(Exception e){  
               Log.e(this.getClass().getName(), e.getMessage());  
          }

需要实现验证的两个类

private class MyHostnameVerifier implements HostnameVerifier{  
            @Override  
            public boolean verify(String hostname, SSLSession session) {  
                    // TODO Auto-generated method stub  
                    return true;  
            }  
  
       }  
  
       private class MyTrustManager implements X509TrustManager{  
            @Override  
            public void checkClientTrusted(X509Certificate[] chain, String authType)  
                            throws CertificateException {  
                    // TODO Auto-generated method stub    
            }  
            @Override  
            public void checkServerTrusted(X509Certificate[] chain, String authType)  
  
                            throws CertificateException {  
                    // TODO Auto-generated method stub      
            }  
            @Override  
            public X509Certificate[] getAcceptedIssuers() {  
                    // TODO Auto-generated method stub  
                    return null;  
            }          
  
      }     

二、不验证证书带参数方式,此处copy

copy原处:http://my.oschina.net/blackylin/blog/144136

public class HttpClientHelper {
 
    private static HttpClient httpClient;
 
    private HttpClientHelper() {
    }
 
    public static synchronized HttpClient getHttpClient() {
 
        if (null == httpClient) {
            // 初始化工作
            try {
                KeyStore trustStore = KeyStore.getInstance(KeyStore
                        .getDefaultType());
                trustStore.load(null, null);
                SSLSocketFactory sf = new SSLSocketFactoryEx(trustStore);
                sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);  //允许所有主机的验证
 
                HttpParams params = new BasicHttpParams();
 
                HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
                HttpProtocolParams.setContentCharset(params,
                        HTTP.DEFAULT_CONTENT_CHARSET);
                HttpProtocolParams.setUseExpectContinue(params, true);
 
                // 设置连接管理器的超时
                ConnManagerParams.setTimeout(params, 10000);
                // 设置连接超时
                HttpConnectionParams.setConnectionTimeout(params, 10000);
                // 设置socket超时
                HttpConnectionParams.setSoTimeout(params, 10000);
 
                // 设置http https支持
                SchemeRegistry schReg = new SchemeRegistry();
                schReg.register(new Scheme("http", PlainSocketFactory
                        .getSocketFactory(), 80));
                schReg.register(new Scheme("https", sf, 443));
 
                ClientConnectionManager conManager = new ThreadSafeClientConnManager(
                        params, schReg);
 
                httpClient = new DefaultHttpClient(conManager, params);
            } catch (Exception e) {
                e.printStackTrace();
                return new DefaultHttpClient();
            }
        }
        return httpClient;
    }
 
}
 
class SSLSocketFactoryEx extends SSLSocketFactory {
 
    SSLContext sslContext = SSLContext.getInstance("TLS");
 
    public SSLSocketFactoryEx(KeyStore truststore)
            throws NoSuchAlgorithmException, KeyManagementException,
            KeyStoreException, UnrecoverableKeyException {
        super(truststore);
 
        TrustManager tm = new X509TrustManager() {
 
            @Override
            public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                return null;
            }
 
            @Override
            public void checkClientTrusted(
                    java.security.cert.X509Certificate[] chain, String authType)
                    throws java.security.cert.CertificateException {
 
            }
 
            @Override
            public void checkServerTrusted(
                    java.security.cert.X509Certificate[] chain, String authType)
                    throws java.security.cert.CertificateException {
 
            }
        };
 
        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();
    }
}

1.浏览器访问https地址,保存提示的证书到本地,放到android项目中的assets目录。
2.导入证书,代码如下。
3.把证书添加为信任。

String requestHTTPSPage(String mUrl) {
        InputStream ins = null;
        String result = "";
        try {
            ins = context.getAssets().open("app_pay.cer"); //下载的证书放到项目中的assets目录中
            CertificateFactory cerFactory = CertificateFactory
                    .getInstance("X.509");
            Certificate cer = cerFactory.generateCertificate(ins);
            KeyStore keyStore = KeyStore.getInstance("PKCS12", "BC");
            keyStore.load(null, null);
            keyStore.setCertificateEntry("trust", cer);
 
            SSLSocketFactory socketFactory = new SSLSocketFactory(keyStore);
            Scheme sch = new Scheme("https", socketFactory, 443);
            HttpClient mHttpClient = new DefaultHttpClient();
            mHttpClient.getConnectionManager().getSchemeRegistry()
                    .register(sch);
 
            BufferedReader reader = null;
            try {
                Log.d(TAG, "executeGet is in,murl:" + mUrl);
                HttpGet request = new HttpGet();
                request.setURI(new URI(mUrl));
                HttpResponse response = mHttpClient.execute(request);
                if (response.getStatusLine().getStatusCode() != 200) {
                    request.abort();
                    return result;
                }
 
                reader = new BufferedReader(new InputStreamReader(response
                        .getEntity().getContent()));
                StringBuffer buffer = new StringBuffer();
                String line = null;
                while ((line = reader.readLine()) != null) {
                    buffer.append(line);
                }
                result = buffer.toString();
                Log.d(TAG, "mUrl=" + mUrl + "\nresult = " + result);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (reader != null) {
                    reader.close();
                }
            }
        } catch (Exception e) {
            // TODO: handle exception
        } finally {
            try {
                if (ins != null)
                    ins.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return result;
    }


服务器端证书验证

原文:http://www.eoeandroid.com/thread-197276-1-1.html
AssetManager am = context.getAssets();
 
    InputStream ins = am.open("robusoft.cer");
 
    try {
 
            //读取证书
 
            CertificateFactory cerFactory = CertificateFactory.getInstance("X.509");  //问1
 
            Certificate cer = cerFactory.generateCertificate(ins);
 
            //创建一个证书库,并将证书导入证书库
 
            KeyStore keyStore = KeyStore.getInstance("PKCS12", "BC");   //问2
 
            keyStore.load(null, null);
 
            keyStore.setCertificateEntry("trust", cer);
 
            return keyStore;
 
    } finally {
 
            ins.close();
 
    }
 
    //把咱的证书库作为信任证书库
 
    SSLSocketFactory socketFactory = new SSLSocketFactory(keystore);
 
    Scheme sch = new Scheme("https", socketFactory, 443);
 
    //完工
 
    HttpClient mHttpClient = new DefaultHttpClient();
 
    mHttpClient.getConnectionManager().getSchemeRegistry().register(sch);
 


问1:这里用"PKCS12"不行 
答1:PKCS12和JKS是keystore的type,不是Certificate的type,所以X.509不能用PKCS12代替


问2:这里用"JKS"不行。


答2:android平台上支持的keystore type好像只有PKCS12,不支持JKS,所以不能用JKS代替在PKCS12,不过在windows平台上是可以代替的

0 0
原创粉丝点击