Android Https相关完全解析 当OkHttp遇到Https

@Override

public void onResponse(String u)

{

mTv.setText(u);

}

});

这样即可访问成功。完整代码已经更新至:https://github.com/hongyangAndroid/okhttp-utils,可以下载里面的sample进行测试,里面包含12306的证书。

ok,到这就可以看到使用Okhttp可以很方便的应对自签名的网站的访问,只需要拿到包含公钥的证书即可。


(二)、使用字符串替代证书

下面继续,有些人可能觉得把证书copy到assets下还是觉得不舒服,其实我们还可以将证书中的内容提取出来,写成字符串常量,这样就不需要证书根据着app去打包了。

zhydeMacBook-Pro:temp zhy$ keytool -printcert -rfc -file srca.cer

-----BEGIN CERTIFICATE-----

MIICmjCCAgOgAwIBAgIIbyZr5/jKH6QwDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCQ04xKTAn

BgNVBAoTIFNpbm9yYWlsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MQ0wCwYDVQQDEwRTUkNBMB4X

DTA5MDUyNTA2NTYwMFoXDTI5MDUyMDA2NTYwMFowRzELMAkGA1UEBhMCQ04xKTAnBgNVBAoTIFNp

bm9yYWlsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MQ0wCwYDVQQDEwRTUkNBMIGfMA0GCSqGSIb3

DQEBAQUAA4GNADCBiQKBgQDMpbNeb34p0GvLkZ6t72/OOba4mX2K/eZRWFfnuk8e5jKDH+9BgCb2

9bSotqPqTbxXWPxIOz8EjyUO3bfR5pQ8ovNTOlks2rS5BdMhoi4sUjCKi5ELiqtyww/XgY5iFqv6

D4Pw9QvOUcdRVSbPWo1DwMmH75It6pk/rARIFHEjWwIDAQABo4GOMIGLMB8GA1UdIwQYMBaAFHle

tne34lKDQ+3HUYhMY4UsAENYMAwGA1UdEwQFMAMBAf8wLgYDVR0fBCcwJTAjoCGgH4YdaHR0cDov

LzE5Mi4xNjguOS4xNDkvY3JsMS5jcmwwCwYDVR0PBAQDAgH+MB0GA1UdDgQWBBR5XrZ3t+JSg0Pt

x1GITGOFLABDWDANBgkqhkiG9w0BAQUFAAOBgQDGrAm2U/of1LbOnG2bnnQtgcVaBXiVJF8LKPaV

23XQ96HU8xfgSZMJS6U00WHAI7zp0q208RSUft9wDq9ee///VOhzR6Tebg9QfyPSohkBrhXQenvQ

og555S+C3eJAAVeNCTeMS3N/M5hzBRJAoffn3qoYdAO1Q8bTguOi+2849A==

-----END CERTIFICATE-----

使用keytool命令,以rfc样式输出。keytool命令是JDK里面自带的。

有了这个字符串以后,我们就不需要srca.cer这个文件了,直接编写以下代码:

public class MyApplication extends Application

{

private String CER_12306 = “-----BEGIN CERTIFICATE-----\n” +

“MIICmjCCAgOgAwIBAgIIbyZr5/jKH6QwDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCQ04xKTAn\n” +

“BgNVBAoTIFNpbm9yYWlsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MQ0wCwYDVQQDEwRTUkNBMB4X\n” +

“DTA5MDUyNTA2NTYwMFoXDTI5MDUyMDA2NTYwMFowRzELMAkGA1UEBhMCQ04xKTAnBgNVBAoTIFNp\n” +

“bm9yYWlsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MQ0wCwYDVQQDEwRTUkNBMIGfMA0GCSqGSIb3\n” +

“DQEBAQUAA4GNADCBiQKBgQDMpbNeb34p0GvLkZ6t72/OOba4mX2K/eZRWFfnuk8e5jKDH+9BgCb2\n” +

“9bSotqPqTbxXWPxIOz8EjyUO3bfR5pQ8ovNTOlks2rS5BdMhoi4sUjCKi5ELiqtyww/XgY5iFqv6\n” +

“D4Pw9QvOUcdRVSbPWo1DwMmH75It6pk/rARIFHEjWwIDAQABo4GOMIGLMB8GA1UdIwQYMBaAFHle\n” +

“tne34lKDQ+3HUYhMY4UsAENYMAwGA1UdEwQFMAMBAf8wLgYDVR0fBCcwJTAjoCGgH4YdaHR0cDov\n” +

“LzE5Mi4xNjguOS4xNDkvY3JsMS5jcmwwCwYDVR0PBAQDAgH+MB0GA1UdDgQWBBR5XrZ3t+JSg0Pt\n” +

“x1GITGOFLABDWDANBgkqhkiG9w0BAQUFAAOBgQDGrAm2U/of1LbOnG2bnnQtgcVaBXiVJF8LKPaV\n” +

“23XQ96HU8xfgSZMJS6U00WHAI7zp0q208RSUft9wDq9ee///VOhzR6Tebg9QfyPSohkBrhXQenvQ\n” +

“og555S+C3eJAAVeNCTeMS3N/M5hzBRJAoffn3qoYdAO1Q8bTguOi+2849A==\n” +

“-----END CERTIFICATE-----”;

@Override

public void onCreate()

{

super.onCreate();

OkHttpClientManager.getInstance()

.setCertificates(new Buffer()

.writeUtf8(CER_12306)

.inputStream());

}

注意Buffer是okio包下的,okhttp依赖okio。

ok,这样就省去将cer文件一起打包进入apk了。


接下来介绍,如何去生成证书以及在tomcat服务器下使用自签名证书部署服务。如果大家没这方面需要可以简单了解下。

四、tomcat下使用自签名证书部署服务

首先自行下载个tomcat的压缩包。

既然我们要支持https,那么肯定需要个证书,如何生成证书呢?使用keytool非常简单。

(一)生成证书

zhydeMacBook-Pro:temp zhy$ keytool -genkey -alias zhy_server -keyalg RSA -keystore zhy_server.jks -validity 3600 -storepass 123456

您的名字与姓氏是什么?

您的组织单位名称是什么?

您的组织名称是什么?

您所在的城市或区域名称是什么?

您所在的省/市/自治区名称是什么?

该单位的双字母国家/地区代码是什么?

CN=zhang, OU=zhang, O=zhang, L=xian, ST=shanxi, C=cn是否正确?

输入 <zhy_server> 的密钥口令

(如果和密钥库口令相同, 按回车):

使用以上命令即可生成一个证书请求文件zhy_server.jks,注意密钥库口令为:123456.

接下来利用zhy_server.jks来签发证书:

zhydeMacBook-Pro:temp zhy$ keytool -export -alias zhy_server

-file zhy_server.cer

-keystore zhy_server.jks

-storepass 123456

即可生成包含公钥的证书zhy_server.cer

(二)、配置Tomcat

找到tomcat/conf/sever.xml文件,并以文本形式打开。

在Service标签中,加入:

<Connector SSLEnabled=“true” acceptCount=“100” clientAuth=“false”

disableUploadTimeout=“true” enableLookups=“true” keystoreFile=“” keystorePass=“123456” maxSpareThreads=“75”

maxThreads=“200” minSpareThreads=“5” port=“8443”

protocol=“org.apache.coyote.http11.Http11NioProtocol” scheme=“https”

secure=“true” sslProtocol=“TLS”

/>

注意keystoreFile的值为我们刚才生成的jks文件的路径:/Users/zhy/ temp/zhy_server.jks(填写你的路径).keystorePass值为密钥库密码:123456

然后启动即可,对于命令行启动,依赖环境变量JAVA_HOME;如果在MyEclispe等IDE下启动就比较随意了。

启动成功以后,打开浏览器输入url:https://localhost:8443/即可看到证书不可信任的警告了。选择打死也要进入,即可进入tomcat默认的主页:

如果你在此tomcat中部署了项目,即可按照如下url方式访问:

https://192.168.1.103:8443/项目名/path,没有部署也没关系,直接拿默认的主页进行测试了,拿它的html字符串。

对于访问,还需要说么,我们刚才已经生成了zhy_server.cer证书。你可以选择copy到assets,或者通过命令拿到内部包含的字符串。我们这里选择copy。

依然选择在Application中设置信任证书:

public class MyApplication extends Application

{

private String CER_12306 = “省略…”;

@Override

public void onCreate()

{

super.onCreate();

try

{

OkHttpClientManager.getInstance()

.setCertificates(

new Buffer()

.writeUtf8(CER_12306).inputStream(),

getAssets().open(“zhy_server.cer”)

);

} catch (IOException e)

{

e.printStackTrace();

}

}

}

ok,这样就能正常访问你部署的https项目中的服务了,没有部署项目的尝试拿https://服务端ip:8443/测试即可。

注意:不要使用localhost,真机测试保证手机和服务器在同一局域网段内。

ok,到此我们介绍完了如果搭建https服务和如何访问,基本上可以应付极大部分的需求了。当然还是极少数的应用需要双向证书验证,比如银行、金融类app,我们一起来了解下。

五、双向证书验证

首先对于双向证书验证,也就是说,客户端也会有个“kjs文件”,服务器那边会同时有个“cer文件”与之对应。

我们已经生成了zhy_server.kjszhy_server.cer文件。

接下来按照生成证书的方式,再生成一对这样的文件,我们命名为:zhy_client.kjs,zhy_client.cer.

(一)配置服务端

首先我们配置服务端:

服务端的配置比较简单,依然是刚才的Connector标签,不过需要添加些属性。

<Connector 其他属性与前面一致

clientAuth=“true”

truststoreFile=“/Users/zhy/temp/zhy_client.cer”

/>

clientAuth设置为true,并且多添加一个属性truststoreFile,理论上值为我们的cer文件。这么加入以后,尝试启动服务器,会发生错误:Invalid keystore format。说keystore的格式不合法。

我们需要对zhy_client.cer执行以下步骤,将证书添加到kjs文件中。

keytool -import -alias zhy_client

-file zhy_client.cer -keystore zhy_client_for_sever.jks

接下里修改server.xml为:

<Connector 其他属性与前面一致

clientAuth=“true”

truststoreFile=“/Users/zhy/temp/zhy_client_for_sever.jks”

/>

此时启动即可。

此时再拿浏览器已经无法访问到我们的服务了,会显示基于证书的身份验证失败

我们将目标来到客户端,即我们的Android端,我们的Android端,如何设置kjs文件呢。

(二)配置app端

目前我们app端依靠的应该是zhy_client.kjs

ok,大家还记得,我们在支持https的时候调用了这么俩行代码:

sslContext.init(null, trustManagerFactory.getTrustManagers(),

new SecureRandom());

mOkHttpClient.setSslSocketFactory(sslContext.getSocketFactory());

注意sslContext.init的第一个参数我们传入的是null,第一个参数的类型实际上是KeyManager[] km,主要就用于管理我们客户端的key。

于是代码可以这么写:

public void setCertificates(InputStream… certificates)

{

try

{

CertificateFactory certificateFactory = CertificateFactory.getInstance(“X.509”);

KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());

keyStore.load(null);

int index = 0;

for (InputStream certificate : certificates)

{

String certificateAlias = Integer.toString(index++);

keyStore.setCertificateEntry(certificateAlias, certificateFactory.generateCertificate(certificate));

try

{

if (certificate != null)

certificate.close();

} catch (IOException e)

{

}

}

SSLContext sslContext = SSLContext.getInstance(“TLS”);

TrustManagerFactory trustManagerFactory = TrustManagerFactory.

getInstance(TrustManagerFactory.getDefaultAlgorithm());

trustManagerFactory.init(keyStore);

//初始化keystore

KeyStore clientKeyStore = KeyStore.getInstance(KeyStore.getDefaultType());

clientKeyStore.load(mContext.getAssets().open(“zhy_client.jks”), “123456”.toCharArray());

KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());

keyManagerFactory.init(clientKeyStore, “123456”.toCharArray());

sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), new SecureRandom());

mOkHttpClient.setSslSocketFactory(sslContext.getSocketFactory());

} catch (Exception e)

{

e.printStackTrace();

}

}

核心代码其实就是:

//初始化keystore

KeyStore clientKeyStore = KeyStore.getInstance(KeyStore.getDefaultType());

clientKeyStore.load(mContext.getAssets().open(“zhy_client.jks”), “123456”.toCharArray());

KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());

keyManagerFactory.init(clientKeyStore, “123456”.toCharArray());

sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), new SecureRandom());

然而此时启动会报错:java.io.IOException: Wrong version of key store.

为什么呢?

因为:Java平台默认识别jks格式的证书文件,但是android平台只识别bks格式的证书文件。

这么就纠结了,我们需要将我们的jks文件转化为bks文件,怎么转化呢?

这里的方式可能比较多,大家可以百度,我推荐一种方式:

Portecle下载Download portecle-1.9.zip (3.4 MB)

解压后,里面包含bcprov.jar文件,使用jave -jar bcprov.jar即可打开GUI界面。

按照上图即可将zhy_client.jks转化为zhy_client.bks

然后将zhy_client.bks拷贝到assets目录下,修改代码为:

最后

简历首选内推方式,速度快,效率高啊!然后可以在拉钩,boss,脉脉,大街上看看。简历上写道熟悉什么技术就一定要去熟悉它,不然被问到不会很尴尬!做过什么项目,即使项目体量不大,但也一定要熟悉实现原理!不是你负责的部分,也可以看看同事是怎么实现的,换你来做你会怎么做?做过什么,会什么是广度问题,取决于项目内容。但做过什么,达到怎样一个境界,这是深度问题,和个人学习能力和解决问题的态度有关了。大公司看深度,小公司看广度。大公司面试你会的,小公司面试他们用到的你会不会,也就是岗位匹配度。

面试过程一定要有礼貌!即使你觉得面试官不尊重你,经常打断你的讲解,或者你觉得他不如你,问的问题缺乏专业水平,你也一定要尊重他,谁叫现在是他选择你,等你拿到offer后就是你选择他了。

另外,描述问题一定要慢!不要一下子讲一大堆,慢显得你沉稳、自信,而且你还有时间反应思路接下来怎么讲更好。现在开发过多依赖ide,所以会有个弊端,当我们在面试讲解很容易不知道某个方法怎么读,这是一个硬伤…所以一定要对常见的关键性的类名、方法名、关键字读准,有些面试官不耐烦会说“你到底说的是哪个?”这时我们会容易乱了阵脚。正确的发音+沉稳的描述+好听的嗓音决对是一个加分项!

最重要的是心态!心态!心态!重要事情说三遍!面试时间很短,在短时间内对方要摸清你的底子还是比较不现实的,所以,有时也是看眼缘,这还是个看脸的时代。

希望大家都能找到合适自己满意的工作!

进阶学习视频

附上:我们之前因为秋招收集的二十套一二线互联网公司Android面试真题 (含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总。)

加入社区》https://bbs.csdn.net/forums/4304bb5a486d4c3ab8389e65ecb71ac0
断你的讲解,或者你觉得他不如你,问的问题缺乏专业水平,你也一定要尊重他,谁叫现在是他选择你,等你拿到offer后就是你选择他了。

另外,描述问题一定要慢!不要一下子讲一大堆,慢显得你沉稳、自信,而且你还有时间反应思路接下来怎么讲更好。现在开发过多依赖ide,所以会有个弊端,当我们在面试讲解很容易不知道某个方法怎么读,这是一个硬伤…所以一定要对常见的关键性的类名、方法名、关键字读准,有些面试官不耐烦会说“你到底说的是哪个?”这时我们会容易乱了阵脚。正确的发音+沉稳的描述+好听的嗓音决对是一个加分项!

最重要的是心态!心态!心态!重要事情说三遍!面试时间很短,在短时间内对方要摸清你的底子还是比较不现实的,所以,有时也是看眼缘,这还是个看脸的时代。

希望大家都能找到合适自己满意的工作!

进阶学习视频

[外链图片转存中…(img-qwdpDOHJ-1725634748429)]

附上:我们之前因为秋招收集的二十套一二线互联网公司Android面试真题 (含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总。)

[外链图片转存中…(img-f9w6Tmns-1725634748429)]

加入社区》https://bbs.csdn.net/forums/4304bb5a486d4c3ab8389e65ecb71ac0

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值