Android如何使用Https?

技术交流1群:46523908
技术交流2群:46505645
NoHttp 源码及Demo:https://github.com/Y0LANDA/NoHttp

NoHttp是专门做Android网络请求与下载的框架。

这一篇文章是NoHttp系列中比较重要的,为大家介绍一下内容:

什么是Https?

  HTTPS(全称:Hyper Text Transfer Protocol over Secure Socket Layer),是以安全为目标的HTTP通道,简单讲是HTTP的安全版。即HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL。它是一个URI Scheme(抽象标识符体系),句法类同Http:体系。用于安全的HTTP数据传输。Https:URL表明它使用了HTTP,但HTTPS存在不同于HTTP的默认端口及一个加密/身份验证层(在HTTP与TCP之间)。这个系统的最初研发由网景公司(NetScape)进行,并内置于其浏览器Netscape Navigator中,提供了身份验证与加密通讯方法。现在它被广泛用于万维网上安全敏感的通讯,例如金融、网购等涉及支付的领域。
  
这次不装逼,我们来个深入浅出,先说最原始的Https,再说框架怎么框架怎么一句话使用Https

Android用原始Java代码怎么用Https

  先普及一下Android怎么用最原始java代码请求网络,大神请掠过。
  Android用Java开发,Java自带的http API有HttpURLConnection,Android系统又加上了Apache Httpclient,加上后来HttpClient在SDK中被Google删除,所以我们也不推荐使用HttpClient来做网络请求了,所以在这里呢也只给列出HttpURLConnection的方式。

第一步:打开某个地址的连接

  这里咱打开我的博客地址,用GET方法请求

URL url = new URL("http://blog.csdn.net/yanzhenjie1003");HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();urlConnection.setRequestMethod("GET");

第二步:判断是Https请求,设置SSLSocketFactory

  如果是Https请求,那么做安全校验等操作,这里设置SSLSokcetFactory,这里有两种方法,一种是包涵Https证书的,一种是没有证书直接允许Https请求的,而证书不证书就是从SSLContext中来的:

// 设置SSLSocketFoactory,这里有两种:1.需要安全证书 2.不需要安全证书;看官且往下看if (urlConnection instanceof HttpsURLConnection) { // 是Https请求    SSLContext sslContext = SSLContextUtil.getSSLContext();    if (sslContext != null) {        SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();        ((HttpsURLConnection) urlConnection).setSSLSocketFactory(sslSocketFactory);    }}

  那么SSLContext怎么生成呢,哈哈先不急,咱们先把这个请求的流程走完,证书的加载往后边看哦。

第三步:设置必要属性

// 设置属性urlConnection.setConnectTimeout(8 * 1000);urlConnection.setReadTimeout(8 * 1000);

第四步:读取数据,发送到主线程,断开连接

int responseCode = urlConnection.getResponseCode();if (responseCode == 200) { // 请求成功    InputStream inputStream = urlConnection.getInputStream();    // 读取结果,发送到主线程    ...    inputStream.close();}urlConnection.disconnect();

完整代码

URL url = new URL("http://blog.csdn.net/yanzhenjie1003");HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();urlConnection.setRequestMethod("GET");// 设置SSLSocketFoactory,这里有两种:1.需要安全证书 2.不需要安全证书;看官且往下看if (urlConnection instanceof HttpsURLConnection) { // 是Https请求    SSLContext sslContext = SSLContextUtil.getSSLContext();    if (sslContext != null) {        SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();        ((HttpsURLConnection) urlConnection).setSSLSocketFactory(sslSocketFactory);    }}// 设置属性urlConnection.setConnectTimeout(8 * 1000);urlConnection.setReadTimeout(8 * 1000);int responseCode = urlConnection.getResponseCode();if (responseCode == 200) { // 请求成功    InputStream inputStream = urlConnection.getInputStream();    // 读取结果,发送到主线程    ...    inputStream.close();}urlConnection.disconnect();

这样就完成整个请求,其实Android请求网络就这么点代码,然后我们再写完善一点,然后封装写参数,容错什么的,就是一个小框架啦。是不是很简单呢?

使用流行框架NoHttp怎么玩Https

  用NoHttp不要太简单,什么传参数、传文件、下载之类的,基本都是一两句话就搞定。

Request<String> request = NoHttp.createStringRequest(url, RequestMethod.POST);// 注意这里设置SSLSokcetFactory的代码是相同的SSLContext sslContext = SSLContextUtil.getSSLContext();if (sslContext != null) {    SSLSocketFactory socketFactory = sslContext.getSocketFactory();    httpsRequest.setSSLSocketFactory(socketFactory);    requestQueue.add(0, request, httpListener);// 添加到请求队列,等待接受结果}

  我们注意到上面设置Socket的代码是相同的,剩下的就是一句话new一个请求对象就完事。是不是比原生的还要简单啊?

  这个框架叫NoHttp,是一个Android开源网络框架。
源码托管在:https://github.com/Y0LANDA/NoHttp
教程博客:http://blog.csdn.net/yanzhenjie1003

SSLSocketFactory对象怎么来

  上面不论是纯Android代码还是NoHttp框架都用到了SSLContext,这家伙呢就是负责证书管理和信任管理器的,我们说Https可以有证书也可以没有证书,我们来看这两种情况。

有安全证书的SSLContext

我们把Https的证书放在assets目录下,然后通过流加载:

public static SSLContext getSSLContext() {    // 生成SSLContext对象    SSLContext sslContext = SSLContext.getInstance("TLS");    // 从assets中加载证书    InputStream inStream = Application.getInstance().getAssets().open("srca.cer");    // 证书工厂    CertificateFactory cerFactory = CertificateFactory.getInstance("X.509");    Certificate cer = cerFactory.generateCertificate(inStream);    // 密钥库    KeyStore kStore = KeyStore.getInstance("PKCS12");    kStore.load(null, null);    kStore.setCertificateEntry("trust", cer);// 加载证书到密钥库中    // 密钥管理器    KeyManagerFactory keyFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());    keyFactory.init(kStore, null);// 加载密钥库到管理器    // 信任管理器    TrustManagerFactory tFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());tFactory.init(kStore);// 加载密钥库到信任管理器    // 初始化    sslContext.init(keyFactory.getKeyManagers(), tFactory.getTrustManagers(), new SecureRandom());    return sslContext;}

  需要强调的是,最后一句中的new SecureRandom()在Android4.4之前的系统中有Bug。
  

修复Android系统中SecureRandom的Bug

  Android 4.4之前版本的Java加密架构(JCA)中使用的Apache Harmony 6.0M3及其之前版本的SecureRandom实现存在安全漏洞,具体位于classlib/modules/security/src/main/java/common/org/apache/harmony/security/provider/crypto/SHA1PRNG_SecureRandomImpl.java文件的engineNextBytes()方法里。当用户没有提供用于产生随机数的种子时,程序不能正确调整偏移量,导致伪随机数生成器(PRNG)生成随机序列的过程可被预测。
   But值得高兴的NoHttp内部已经fix了这一bug,如果大家要自己写框架,恐怕要写很多代码去修复这个问题啦,所以推荐各位看官还是使用NoHttp。
   

没有安全证书的SSLContext

  上面看到需要需要安全证书的生成SSLContext就可以了,然后不需要证书的请求,需要两个对象,一个是SSLContext(上面已经解释过了);另一个是HostnameVerifier,顾名思义就是主机名称匹配的意思,我们看代码。

public static SSLContext getSLLContext() {    SSLContext sslContext = null;    try {        sslContext = SSLContext.getInstance("TLS");        sslContext.init(null, new TrustManager[]{new X509TrustManager() {            @Override            public void checkClientTrusted(X509Certificate[] chain, String authType)  {}            @Override            public void checkServerTrusted(X509Certificate[] chain, String authType) {}            @Override            public X509Certificate[] getAcceptedIssuers() {                return new X509Certificate[0];            }        }}, new SecureRandom());    } catch (Exception e) {        e.printStackTrace();    }    return sslContext;}

  就这么简单,只需要传一个null证书管理器喝一个默认的信任管理器即可。
  下面再来看HostnameVerifier,既然是主机名称校验,那我们直接通过:

private static HostnameVerifier hostnameVerifier = new HostnameVerifier() {    @Override    public boolean verify(String hostname, SSLSession session) {        return true;    }};

  这个怎么用呢?Android原生代码用法中,获取SSLContext的方法名不一样,多了setHostnameVerifier,其它跟有安全证书的使用一致:

URL url = new URL("http://blog.csdn.net/yanzhenjie1003");HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();urlConnection.setRequestMethod("GET");// 设置SSLSocketFoactory,这里有两种:1.需要安全证书 2.不需要安全证书;看官且往下看if (urlConnection instanceof HttpsURLConnection) { // 是Https请求    SSLContext sslContext = SSLContextUtil.getSSLContext();    if (sslContext != null) {        SSLSocketFactory sslSocketFactory = sslContext.getSLLContextNoCertificate();        ((HttpsURLConnection) urlConnection).setSSLSocketFactory(sslSocketFactory);        ((HttpsURLConnection) urlConnection).setHostnameVerifier(SSLContextUtil.hostnameVerifier);    }}// 设置属性urlConnection.setConnectTimeout(8 * 1000);urlConnection.setReadTimeout(8 * 1000);int responseCode = urlConnection.getResponseCode();if (responseCode == 200) { // 请求成功    InputStream inputStream = urlConnection.getInputStream();    // 读取结果,发送到主线程    ...    inputStream.close();}urlConnection.disconnect();

  NoHttp用法,代码和上边的NoHttp加载证书的一样,多了一句setHostnameVerifier的:

Request<String> request = NoHttp.createStringRequest(url, RequestMethod.POST);SSLContext sslContext = SSLContextUtil.getSSLContext();if (sslContext != null) {    SSLSocketFactory socketFactory = sslContext.getSLLContextNoCertificate();    httpsRequest.setSSLSocketFactory(socketFactory);    httpsRequest.setHostnameVerifier(SSLContextUtil.hostnameVerifier);    requestQueue.add(0, request, httpListener);// 添加到请求队列,等待接受结果}

如果大家通读了全文,我相信已经会使用Android的Https了吧?不会的在文章下面留言喔。

NoHttp 源码及Demo:https://github.com/Y0LANDA/NoHttp

更多相关文章

  1. Android多媒体框架初步分析
  2. Android 源代码在线查看(转)
  3. Android中获取网页表单中的数据实现思路及代码
  4. android安装包apk文件反编译代码
  5. Android Framework 框架系列之 AlarmManagerService(一)
  6. GDB在线调试Android Framework Native C/C++代码
  7. android 发送短信,彩信,邮件代码
  8. 关机重启代码
  9. Android 重启应用代码

随机推荐

  1. android 判断 无线是否可用
  2. 弹出NumberPicker窗口,修改字体大小
  3. Android(安卓)重启应用本身
  4. Building Local Unit Tests
  5. android 去home
  6. 第一行代码第三章源码整理
  7. 自定义Android侧滑菜单控件
  8. Android(安卓)WebView基本用法及常见问题
  9. Android(安卓)分区详解: boot, system, r
  10. GPS的开关设置