android httpClient 支持HTTPS的访问方式

移动开发 Android
项目中Android https请求地址遇到了这个异常,javax.net.ssl.SSLPeerUnverifiedException: No peer certificate,是SSL协议中没有终端认证。

项目中Android https请求地址遇到了这个异常(无终端认证):
javax.net.ssl.SSLPeerUnverifiedException: No peer certificate

是SSL协议中没有终端认证。

没有遇到过的问题,于是无奈的去找度娘。。。。。。。

看了不少大神的博客后得到的解决方案如下:

  1. /** 
  2.   * Post请求连接Https服务 
  3.   * @param serverURL  请求地址 
  4.   * @param jsonStr    请求报文 
  5.   * @return 
  6.   * @throws Exception 
  7.   */ 
  8.  public static synchronized String doHttpsPost(String serverURL, String jsonStr)throws Exception { 
  9.      // 参数 
  10.      HttpParams httpParameters = new BasicHttpParams(); 
  11.      // 设置连接超时 
  12.      HttpConnectionParams.setConnectionTimeout(httpParameters, 3000); 
  13.      // 设置socket超时 
  14.      HttpConnectionParams.setSoTimeout(httpParameters, 3000); 
  15.      // 获取HttpClient对象 (认证) 
  16.      HttpClient hc = initHttpClient(httpParameters); 
  17.      HttpPost post = new HttpPost(serverURL); 
  18.      // 发送数据类型 
  19.      post.addHeader("Content-Type""application/json;charset=utf-8"); 
  20.      // 接受数据类型 
  21.      post.addHeader("Accept""application/json"); 
  22.      // 请求报文 
  23.      StringEntity entity = new StringEntity(jsonStr, "UTF-8"); 
  24.      post.setEntity(entity); 
  25.      post.setParams(httpParameters); 
  26.      HttpResponse response = null
  27.      try { 
  28.          response = hc.execute(post); 
  29.      } catch (UnknownHostException e) { 
  30.          throw new Exception("Unable to access " + e.getLocalizedMessage()); 
  31.      } catch (SocketException e) { 
  32.          e.printStackTrace(); 
  33.      } 
  34.      int sCode = response.getStatusLine().getStatusCode(); 
  35.      if (sCode == HttpStatus.SC_OK) { 
  36.          return EntityUtils.toString(response.getEntity()); 
  37.      } else 
  38.          throw new Exception("StatusCode is " + sCode); 
  39.  } 
  40.  
  41.  private static HttpClient client = null
  42.  /** 
  43.   * 初始化HttpClient对象 
  44.   * @param params 
  45.   * @return 
  46.   */ 
  47.  public static synchronized HttpClient initHttpClient(HttpParams params) { 
  48.      if(client == null){ 
  49.          try { 
  50.              KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); 
  51.              trustStore.load(nullnull); 
  52.                
  53.              SSLSocketFactory sf = new SSLSocketFactoryImp(trustStore); 
  54.              //允许所有主机的验证 
  55.              sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); 
  56.                
  57.              HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1); 
  58.              HttpProtocolParams.setContentCharset(params, HTTP.UTF_8); 
  59.              // 设置http和https支持 
  60.              SchemeRegistry registry = new SchemeRegistry(); 
  61.              registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80)); 
  62.              registry.register(new Scheme("https", sf, 443)); 
  63.                
  64.              ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry); 
  65.                
  66.              return new DefaultHttpClient(ccm, params); 
  67.          } catch (Exception e) { 
  68.              e.printStackTrace(); 
  69.              return new DefaultHttpClient(params); 
  70.          } 
  71.      } 
  72.      return client; 
  73.  } 
  74.  
  75. public static class SSLSocketFactoryImp extends SSLSocketFactory { 
  76.      final SSLContext sslContext = SSLContext.getInstance("TLS"); 
  77.  
  78.      public SSLSocketFactoryImp(KeyStore truststore) 
  79.              throws NoSuchAlgorithmException, KeyManagementException, 
  80.              KeyStoreException, UnrecoverableKeyException { 
  81.          super(truststore); 
  82.  
  83.          TrustManager tm = new X509TrustManager() { 
  84.              public java.security.cert.X509Certificate[] getAcceptedIssuers() { 
  85.                  return null
  86.              } 
  87.  
  88.              @Override 
  89.              public void checkClientTrusted( 
  90.                      java.security.cert.X509Certificate[] chain, 
  91.                      String authType) 
  92.                      throws java.security.cert.CertificateException { 
  93.              } 
  94.  
  95.              @Override 
  96.              public void checkServerTrusted( 
  97.                      java.security.cert.X509Certificate[] chain, 
  98.                      String authType) 
  99.                      throws java.security.cert.CertificateException { 
  100.              } 
  101.          }; 
  102.          sslContext.init(nullnew TrustManager[] { tm }, null); 
  103.      } 
  104.  
  105.      @Override 
  106.      public Socket createSocket(Socket socket, String host, int port, 
  107.              boolean autoClose) throws IOException, UnknownHostException { 
  108.          return sslContext.getSocketFactory().createSocket(socket, host, 
  109.                  port, autoClose); 
  110.      } 
  111.  
  112.      @Override 
  113.      public Socket createSocket() throws IOException { 
  114.          return sslContext.getSocketFactory().createSocket(); 
  115.      } 
  116.  } 

run下,小手发抖的点到测试按钮,深吸口气,咦?没反应。。。马蛋的,工作线程忘记start(),唉,再次run下,终于的有点反应了,神奇的竟然没有报之前的 javax.net.ssl.SSLPeerUnverifiedException: No peer certificate 的异常了。服务端的数据正常返回了。

分析问题:
HTTPS:超文本安全传输协议,和HTTP相比,多了一个SSL/TSL的认证过程,端口为443。

1.peer终端发送一个request,https服务端把支持的加密算法等以证书的形式返回一个身份信息(包含ca颁发机构和加密公钥等)。

2.获取证书之后,验证证书合法性。

3.随机产生一个密钥,并以证书当中的公钥加密。

4.request https服务端,把用公钥加密过的密钥传送给https服务端。

5.https服务端用自己的密钥解密,获取随机值。

6.之后双方传送数据都用此密钥加密后通信。

HTTPS流程清楚后,问题也就明显了,验证证书时,无法验证。

上面提供的解决方案就是添加默认信任全部证书。以此来通过接下来的通信。

但是,这样问题是解决了。但是觉得还是不带靠谱(信任全部证书有点危险)。继续噼噼啪啪的网上搜索一番。又找到了一种解决方案,其过程大致这样的:

1.浏览器访问https地址,保存提示的证书到本地,放到android项目中的assets目录。

2.导入证书,代码如下。

3.把证书添加为信任。

  1. public static String requestHTTPSPage(Context context, String mUrl) { 
  2.         InputStream ins = null
  3.         String result = ""
  4.         try { 
  5.             ins = context.getAssets().open("my.key"); // 下载的证书放到项目中的assets目录中 
  6.             CertificateFactory cerFactory = CertificateFactory.getInstance("X.509"); 
  7.             Certificate cer = cerFactory.generateCertificate(ins); 
  8.             KeyStore keyStore = KeyStore.getInstance("PKCS12""BC"); 
  9.             keyStore.load(nullnull); 
  10.             keyStore.setCertificateEntry("trust", cer); 
  11.   
  12.             SSLSocketFactory socketFactory = new SSLSocketFactory(keyStore); 
  13.             Scheme sch = new Scheme("https", socketFactory, 443); 
  14.             HttpClient mHttpClient = new DefaultHttpClient(); 
  15.             mHttpClient.getConnectionManager().getSchemeRegistry().register(sch); 
  16.   
  17.             BufferedReader reader = null
  18.             try { 
  19.                 HttpGet request = new HttpGet(); 
  20.                 request.setURI(new URI(mUrl)); 
  21.                 HttpResponse response = mHttpClient.execute(request); 
  22.                 if (response.getStatusLine().getStatusCode() != 200) { 
  23.                     request.abort(); 
  24.                     return result; 
  25.                 } 
  26.   
  27.                 reader = new BufferedReader(new InputStreamReader(response 
  28.                         .getEntity().getContent())); 
  29.                 StringBuffer buffer = new StringBuffer(); 
  30.                 String line = null
  31.                 while ((line = reader.readLine()) != null) { 
  32.                     buffer.append(line); 
  33.                 } 
  34.                 result = buffer.toString(); 
  35.             } catch (Exception e) { 
  36.                 e.printStackTrace(); 
  37.             } finally { 
  38.                 if (reader != null) { 
  39.                     reader.close(); 
  40.                 } 
  41.             } 
  42.         } catch (Exception e) { 
  43.             e.printStackTrace(); 
  44.         } finally { 
  45.             try { 
  46.                 if (ins != null
  47.                     ins.close(); 
  48.             } catch (IOException e) { 
  49.                 e.printStackTrace(); 
  50.             } 
  51.         } 
  52.         return result; 

本文链接:http://my.oschina.net/u/1251149/blog/299010

责任编辑:chenqingxiang 来源: oschina
相关推荐

2017-10-23 13:20:37

2017-06-07 11:37:47

2018-11-30 16:17:28

HTTPS

2019-04-24 11:41:32

云计算开发数据中心

2010-09-13 12:19:03

2011-12-09 20:28:50

2017-05-24 09:43:42

2013-03-26 13:38:12

Android per

2018-10-29 15:20:03

2010-08-13 08:57:20

Flex主题

2021-07-14 15:01:14

智能电网技术物联网

2022-02-23 12:35:12

LibreOffic无障碍辅助套件

2010-05-31 17:56:27

2021-09-15 08:09:43

前端技术编程

2020-10-16 08:02:00

Android系统

2010-03-16 11:07:19

ArrayiPhone应用交付

2013-06-08 13:37:28

Android开发XML解析Pull方式

2015-04-20 10:45:43

2010-04-16 16:39:25

Oracle细粒度

2020-09-27 10:17:08

区块链物联网IOT
点赞
收藏

51CTO技术栈公众号