什么是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");
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

第二步:判断是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);
}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

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

第三步:设置必要属性

// 设置属性
urlConnection.setConnectTimeout(8 * 1000);
urlConnection.setReadTimeout(8 * 1000);
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

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

int responseCode = urlConnection.getResponseCode();
if (responseCode == 200) { // 请求成功
InputStream inputStream = urlConnection.getInputStream();
// 读取结果,发送到主线程
...
inputStream.close();
}
urlConnection.disconnect();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

完整代码

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();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

这样就完成整个请求,其实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);// 添加到请求队列,等待接受结果
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

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

  这个框架叫NoHttp,是一个Android开源网络框架。 源码托管在:https://github.com/yanzhenjie/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;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

  需要强调的是,最后一句中的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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

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

private static HostnameVerifier hostnameVerifier = new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

  这个怎么用呢?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();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

  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);// 添加到请求队列,等待接受结果
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

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

Android如何使用Https的更多相关文章

  1. Android安全之Https中间人攻击漏洞

    Android安全之Https中间人攻击漏洞 0X01 概述   HTTPS,是一种网络安全传输协议,利用SSL/TLS来对数据包进行加密,以提供对网络服务器的身份认证,保护交换数据的隐私与完整性. ...

  2. android http 和https请求

    private static final int CONNECTION_TIMEOUT = 10000; public static String doHttpGet(String serverURL ...

  3. Android进阶(二)https请求No peer certificate的解决方法.

    在做Android客户端通过https协议访问12306,并爬取数据时,出现了如下错误: 其中有一条错误提示是 javax.net.ssl.SSLPeerUnverifiedException: No ...

  4. android webview 访问https页面 SslError 处理

    在Android中,WebView可以用来加载http和https网页到本地应用的控件.但是在默认情况下,通过loadUrl(String url)方法,可以顺利loadUrl(“http://www ...

  5. android httpClient 支持HTTPS的2种处理方式

    摘自: http://www.kankanews.com/ICkengine/archives/9634.shtml 项目中Android https或http请求地址重定向为HTTPS的地址,相信很 ...

  6. android httpClient 支持HTTPS的访问方式

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

  7. Android进阶(三)android httpClient 支持HTTPS的访问方式

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

  8. 解决Android无法正常https://dl.google.com/dl/android/maven2/com/的办法

    最近需要进行移动开发,在安装Android Studio时,遇到了很纠结的问题,安装一直很不顺利.经过2天的百度搜索终于是找到解决的办法. 问题花了2天的时间才从茫茫大海中找到确切的答案.所以必须开个 ...

  9. android webview 访问 https 页面

    在android 中利用webview 控件进行开发过程中,可能会遇到 webview 访问不了https://的页面如 https://www.google.com.hk 重写onReceivedS ...

随机推荐

  1. 升级 macOS Mojave 后部分软件 (如 VS Code) 字体变虚的解决方法

    目前有些朋友的设备可能还是“非 Retina” 显示器,那这样如果升级到 Mojave 后你会发现文字不清晰了,这是因为 Mojave 默认关闭了文字次像素渲染字体,你需要在终端里执行: defaul ...

  2. Arpa’s obvious problem and Mehrdad’s terrible solution 思维

    There are some beautiful girls in Arpa’s land as mentioned before. Once Arpa came up with an obvious ...

  3. Dataframe 中的 and vs &

    refer to: http://dougaoyang.github.io/2017/09/22/pandas-bool-compare.html df[(df['pop']>3) and (d ...

  4. BL老师的建议,数学不好的,大数据一票否决--后赋从java转大数据

    __________________________ 作者:我是蛋蛋链接:https://www.zhihu.com/question/59593387/answer/167235075来源:知乎著作 ...

  5. device public set

    backgroud:  our dvertiser provide on device list of idfa to show ad to  target audience,however none ...

  6. XDomainRequest object

    The XDomainRequest object has these types of members: Events Methods Properties Events The XDomainRe ...

  7. 彻底删除vscode及安装的插件和个人配置信息

    1.卸载vscode应用软件(在控制面板里面找不到改软件,所以只能进入应用所在文件夹进行卸载) ## 此步骤虽然删掉了应用软件,但是此时重新安装会发现之前下载的插件和个人配置信息都还会重新加载出来,所 ...

  8. 4.图像sensor的特性和驱动解析

    修改 摄像头SDK中支持的sensor需要做的事 例如:ar0130 --> ov9712 1.修改加载load3518e脚本的参数 vi /etc/profile ./load3518e -i ...

  9. 让node支持es模块化(export、import)的方法

    node版本v7.9.0,支持了大部分es6的功能,但还不支持es6模块化(export.import). 检测ES6 可以使用es-checker来检测当前Node.js对ES6的支持情况. 使用命 ...

  10. IdentityHashMap 与 HashMap 的区别

    IdentityHashMap 中的 key 允许重复 IdentityHashMap 使用的是 == 比较 key 的值(比较内存地址),而 HashMap 使用的是 equals()(比较存储值) ...