近期由于公司的工作需要,需要将原有的http接口切换到https,故做了如下学习和整理。本文先简要说明https协议原理,然后https协议在浏览器和App的实践两方面进行讲述;
一、https协议原理
1.要理解https是什么,我们必须应该理解如下几个关键词,和它们之间的关系:
http:超文本传输协议,广泛用于从WWW服务器传输超文本到本地浏览器的传输协议;
SSL/TLS:最广泛的密码通信方案,综合运用了对称密码、消息认证码、公钥密码、数字签名、伪随机数生成密码等密码技术;
https:在SSL/TLS之上承载HTTP,将两种协议进行叠加;
![](https://img-blog.csdn.net/20161202175431826?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
2.在继续讲解https之前,我们得先了解下几个密码学套件,对于比较好理解的对称密码和非对称密码就不进行详细的讲解了:
![](https://img-blog.csdn.net/20161202175444983?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
单项散列函数:根据任意长度的消息计算出固定长度的散列值,来确定文件的完整性;
![](https://img-blog.csdn.net/20161202175527259?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
消息认证码:是一种密钥相关联的单向散列函数。要计算MAC必须持有共享秘钥,消息变化MAC值就会不一致,故验证身份和完整性;
![](https://img-blog.csdn.net/20161202175539297?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
数字签名:反用密钥对,使用自己私钥加密生成签名,验证方用你的公钥能解密即可验证加密方是你,故能验证身份和完整性;
![](https://img-blog.csdn.net/20161202175603431?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
公钥证书:认证机构通过电话、邮件或本人确认后,使用机构的私钥对你的公钥进行签名,保证了你的公钥的正确性;
![](https://img-blog.csdn.net/20161202175615712?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
3.完成基本密码套件的学习,接下来我们继续介绍https。由上可知https的核心在于SSL/TLS,让主要解决了如下接个问题:
机密性:信息传输过程中的被第三方窃听—采用对称密码加密,伪随机数生成器密钥,公钥密码或Diffe-Hellman进行公钥交换;
完整性:信息传输过程中被中间人篡改—采用单向散列函的消息认证码进行完整性验证;
认证性:信息传输的对方身份是否合法—对公钥加上数字签名所生成的证书,对通信对象进行认证;
4.在https的进行通信的过程中,它是如何有序的运用上面的密码学套件的呢?如下:
该部分是基于TLS1.0进行说明,TLS协议是由“TLS记录协议”和“TLS握手协议”这两层协议叠加而成:
![](https://img-blog.csdn.net/20161202175627946?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
1.握手协议:除加密之外的各种工作,分为4个子协议:握手协议、密码规格变更协议、警告协议和应用数据协议;
握手子协议:负责在客户端和服务器之间协商决定密码算法和共享秘钥;
密码规格变更协议:负责向通信对象传达变更密码方式的信号;
警告协议:负责在发生错误的时候将错误传达给对方;
应用数据协议:将TLS上面承载的应用数据传达给通信对象的协议;
![](https://img-blog.csdn.net/20161202175638267?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
2.记录协议:位于TLS握手协议的下层,负责使用对称密码对消息进行压缩、加密以及数据的认证;
消息被分割成多个较短的片段,然后对每个片段进行压缩;
压缩片段会被加上消息认证码,保证完整性,并进行数据的认证,可以识别出篡改。为了防止重放攻击,在计算消息认证码时加上了片段的编号;
经过压缩的片段在加上消息认证码会一起通过对称密码进行加密;
经过加密的数据再加上由数据类型、版本号、压缩后的长度组成的报头就是最终的报文数据;
![](https://img-blog.csdn.net/20161202175648720?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
经过以上的大概讲解,相信大家对https有了更深入的认识,并且也能更好的理解为什么在实践https的时候要生成各种密钥和信任库了。
二、https协议实践
理解上面的相关原理后,我们就开始实现HttpsServlet来模拟简单登录接口,然后通过浏览器和app的访问该https接口;
1.服务端http实现
我们首先实现服务端http协议的get和post通信,项目的结构和主要实现代码如下:
![]()
HttpsServlet.java:
web.xml:
AndroidManifext.xml:
启动服务器tomcat,运行客户端app效果如下:
启动Fiddler抓包如下,Get请求(Post请求可以自行实践)数据包如下,为明文传输!
接下来,我们就开始将当前http连接修改成https,并查看修改后的抓包情况。
2.生成密钥对、证书和信任证书库 (详情请查阅http://docs.oracle.com/javase/7/docs/technotes/tools/solaris/keytool.html)
在生成该操作过程中,我们将主要用Keytool工具:
keytool:是一个Java数据证书的管理工具,keytool将密钥(key)和证书(certificates)存在一个称为keystore的文件中;
keystore:在keystore里,包含两种数据:密钥实体(key entity)-密钥(secret key)又或者是公私钥密钥对、可信任的证书实体(trusted certificate entries)-只包含公钥;
生成服务器证书库
-genkey:创建一个新的密钥;
-alias:密钥别名,每个keystore都关联一个独一无二的别名;
-keyalg:使用的加密算法,使用RSA;
-keystore:密钥存储目录,保存在D:\ssl目录下;
-dname:
CN(Common Name名字与姓氏)
OU(Organization Unit组织单位名称)
O(Organization组织名称)
L(Locality城市或区域名称)
ST(State州或省份名称)
C(Country国家名称)
-storepass:存取密码,这个密码供系统从keystore文件取信息的时候使用;
-keypass:私有密钥的密码;
-validity:有效期,365天;
注意1:生成服务端密钥时,alias必须为tomcat,否则后续启动tomcat服务的时候会报错Caused by: java.io.IOException: Alias name tomcat does not identify a key entry ;
注意2:生成服务端密钥库时,CN必须与服务端的域名或者ip地址相同,否则正常获取证书访问;
从服务器证书库中导出服务器证书
生成客户端信任证书库 (由服务端证书生成的证书库)
注意3:-storetype BKS,是Android上面可以识别的格式。如果不指定,jdk默认生成的格式是JKS。 -provider org.bouncycastle.jce.provider.BouncyCastleProvider,需要下载jar包bcprov-jdk16-146.jar放到JDK_HOME\jre\lib\ext\目录下。 注意需要java1.6,其他的版本android下面有版本不匹配的问题;
生成客户端证书库
从客户端证书库中导出客户端证书
生成服务端信任证书库 (使得服务器信任客户端证书)
查看证书库中的全部证书 (服务器密钥库,客户端密钥库和信任库)
运行完成后,D:\ssl\目录下生成如下文件:
qproject.cer:客户端证书;
qproject.p12:客户端密钥;
qproject.truststore:客户端信任证书库;
tomcat.cer:服务端证书;
tomcat.keysotre:服务端密钥和信任证书库;
3.Tomcat的配置 (详细请查阅:https://tomcat.apache.org/tomcat-9.0-doc/ssl-howto.html)
修改tomcat的配置文件${catalina.base}/conf/server.xml;
port:https访问的端口;
SSLEnabled:true,开启https服务;
scheme:https;
secure:true,开启服务端安全通信,客户端获取服务器端证书;
keystoreFile:D:\ssl\tomcat.keystore;
keystorePass:123456,服务器证书库密码;
clientAuth:true,开启验证客户端;
sslProtocol:TLS,使用的协议;
truststoreFile:D:\ssl\tomcat.keystore,服务器证书库(已导入客户端证书) ;
truststorePass:123456;
提示1:启动tomcat服务器,报错如下:
Caused by: java.io.IOException: Alias name tomcat does not identify a key entry
at org.apache.tomcat.util.net.jsse.JSSEUtil.getKeyManagers(JSSEUtil.java:306)
at org.apache.tomcat.util.net.AbstractJsseEndpoint.initialiseSsl(AbstractJsseEndpoint.java:90)
at org.apache.tomcat.util.net.NioEndpoint.bind(NioEndpoint.java:245)
at org.apache.tomcat.util.net.AbstractEndpoint.init(AbstractEndpoint.java:839)
at org.apache.coyote.AbstractProtocol.init(AbstractProtocol.java:558)
at org.apache.coyote.http11.AbstractHttp11Protocol.init(AbstractHttp11Protocol.java:65)
at org.apache.catalina.connector.Connector.initInternal(Connector.java:1010)
... 13 more
处理1:检查你生成的服务器证书的-alias是否为tomcat
由于我们是在本机测试,并且在生成证书的时候CN配置了www.qserver.com,故我们在测试之前添加Hosts配置如下;
启动tomcat服务器,我们先用浏览器以get的方式测试下服务端https接口功能。 访问成功!服务器接口修改完毕,接下来我们来修改客户端;
![]()
处理2:由于服务器Https握手过程中,交换的证书不在浏览器信任的范围,故提示错误。
4.客户端修改
添加项目目录asset,并在该目录下添加服务端验证客户端的证书qproject.p12,和客户端验证服务端的信任证书库qproject.truststore;
![]()
添加客户端https身份验证等相关逻辑;
HttpsHelper.java:
NextActivity.java: 修改获取HttpsURLConnection的方式,和域名https,其它不变
提示1:在请求https接口的时候,报错如下:
11-06 17:53:36.244 32662-5351/com.qunar.home W/System.err: java.io.IOException: Wrong version of key store.
11-06 17:53:36.245 32662-5351/com.qunar.home W/System.err: at com.android.org.bouncycastle.jcajce.provider.keystore.bc.BcKeyStoreSpi.engineLoad(BcKeyStoreSpi.java:805)
11-06 17:53:36.245 32662-5351/com.qunar.home W/System.err: at java.security.KeyStore.load(KeyStore.java:590)
11-06 17:53:36.245 32662-5351/com.qunar.home W/System.err: at com.qunar.hotel.ssl.HttpsHelper.getSSLContext(HttpsHelper.java:46)
11-06 17:53:36.245 32662-5351/com.qunar.home W/System.err: at com.qunar.hotel.ssl.HttpsHelper.getHttpsURLConnection(HttpsHelper.java:87)
11-06 17:53:36.245 32662-5351/com.qunar.home W/System.err: at com.qunar.hotel.NextActivity.doLoginGet(NextActivity.java:83)
11-06 17:53:36.245 32662-5351/com.qunar.home W/System.err: at com.qunar.hotel.NextActivity.access$300(NextActivity.java:27)
11-06 17:53:36.245 32662-5351/com.qunar.home W/System.err: at com.qunar.hotel.NextActivity$2$1.run(NextActivity.java:67)
11-06 17:53:36.245 32662-5351/com.qunar.home W/System.err: at java.lang.Thread.run(Thread.java:818)
处理:android系统只支持JKS默认证书格式,支持BKS,故生成客户端证书的时候使用DKS格式生成,见上面章节;
提示2:在请求https接口的时候,报错如下:
11-06 18:52:53.154 21260-23016/com.qunar.home W/System.err: java.io.IOException: Hostname '192.168.1.103' was not verified
11-06 18:52:53.154 21260-23016/com.qunar.home W/System.err: at com.android.okhttp.Connection.upgradeToTls(Connection.java:205)
11-06 18:52:53.155 21260-23016/com.qunar.home W/System.err: at com.android.okhttp.Connection.connect(Connection.java:155)
11-06 18:52:53.155 21260-23016/com.qunar.home W/System.err: at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:282)
11-06 18:52:53.155 21260-23016/com.qunar.home W/System.err: at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:216)
11-06 18:52:53.155 21260-23016/com.qunar.home W/System.err: at com.android.okhttp.internal.http.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:391)
11-06 18:52:53.155 21260-23016/com.qunar.home W/System.err: at com.android.okhttp.internal.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:341)
11-06 18:52:53.155 21260-23016/com.qunar.home W/System.err: at com.android.okhttp.internal.http.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:509)
11-06 18:52:53.155 21260-23016/com.qunar.home W/System.err: at com.android.okhttp.internal.http.DelegatingHttpsURLConnection.getResponseCode(DelegatingHttpsURLConnection.java:105)
11-06 18:52:53.155 21260-23016/com.qunar.home W/System.err: at com.android.okhttp.internal.http.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:25)
11-06 18:52:53.155 21260-23016/com.qunar.home W/System.err: at com.qunar.hotel.NextActivity.doLoginGet(NextActivity.java:84)
11-06 18:52:53.155 21260-23016/com.qunar.home W/System.err: at com.qunar.hotel.NextActivity.access$300(NextActivity.java:27)
11-06 18:52:53.155 21260-23016/com.qunar.home W/System.err: at com.qunar.hotel.NextActivity$2$1.run(NextActivity.java:67)
11-06 18:52:53.155 21260-23016/com.qunar.home W/System.err: at java.lang.Thread.run(Thread.java:818)
处理:由于我们在测试环境,故请求url中使用了服务器的ip,到时和证书中的 CN(Common Name名字与姓氏)不匹配(在正式的环境不会有该问题)。那么我们默认跳过该认证或者在正式线使用线上的域名访问:
//忽略请求域名和证书域名的校验
connection.setDefaultHostnameVerifier( new HostnameVerifier(){
public boolean verify(String string,SSLSession ssls) {
return true;
}
});
5.tomcat修改
原来的connector配置只有加解密,现在加上服务端身份验证相关配置,修改server.xml文件如下:
clientAuth:启动客户端身份验证;
truststoreFile:服务端信任的客户端证书库;
truststorePass:信任证书库密码;
6.测试Https接口
安装app,并重新启动tomcat服务,使用Fiddler抓取https请求使用加密传输!
一、https协议原理
1.要理解https是什么,我们必须应该理解如下几个关键词,和它们之间的关系:
http:超文本传输协议,广泛用于从WWW服务器传输超文本到本地浏览器的传输协议;
SSL/TLS:最广泛的密码通信方案,综合运用了对称密码、消息认证码、公钥密码、数字签名、伪随机数生成密码等密码技术;
https:在SSL/TLS之上承载HTTP,将两种协议进行叠加;
2.在继续讲解https之前,我们得先了解下几个密码学套件,对于比较好理解的对称密码和非对称密码就不进行详细的讲解了:
单项散列函数:根据任意长度的消息计算出固定长度的散列值,来确定文件的完整性;
消息认证码:是一种密钥相关联的单向散列函数。要计算MAC必须持有共享秘钥,消息变化MAC值就会不一致,故验证身份和完整性;
数字签名:反用密钥对,使用自己私钥加密生成签名,验证方用你的公钥能解密即可验证加密方是你,故能验证身份和完整性;
公钥证书:认证机构通过电话、邮件或本人确认后,使用机构的私钥对你的公钥进行签名,保证了你的公钥的正确性;
3.完成基本密码套件的学习,接下来我们继续介绍https。由上可知https的核心在于SSL/TLS,让主要解决了如下接个问题:
机密性:信息传输过程中的被第三方窃听—采用对称密码加密,伪随机数生成器密钥,公钥密码或Diffe-Hellman进行公钥交换;
完整性:信息传输过程中被中间人篡改—采用单向散列函的消息认证码进行完整性验证;
认证性:信息传输的对方身份是否合法—对公钥加上数字签名所生成的证书,对通信对象进行认证;
4.在https的进行通信的过程中,它是如何有序的运用上面的密码学套件的呢?如下:
该部分是基于TLS1.0进行说明,TLS协议是由“TLS记录协议”和“TLS握手协议”这两层协议叠加而成:
1.握手协议:除加密之外的各种工作,分为4个子协议:握手协议、密码规格变更协议、警告协议和应用数据协议;
握手子协议:负责在客户端和服务器之间协商决定密码算法和共享秘钥;
密码规格变更协议:负责向通信对象传达变更密码方式的信号;
警告协议:负责在发生错误的时候将错误传达给对方;
应用数据协议:将TLS上面承载的应用数据传达给通信对象的协议;
2.记录协议:位于TLS握手协议的下层,负责使用对称密码对消息进行压缩、加密以及数据的认证;
消息被分割成多个较短的片段,然后对每个片段进行压缩;
压缩片段会被加上消息认证码,保证完整性,并进行数据的认证,可以识别出篡改。为了防止重放攻击,在计算消息认证码时加上了片段的编号;
经过压缩的片段在加上消息认证码会一起通过对称密码进行加密;
经过加密的数据再加上由数据类型、版本号、压缩后的长度组成的报头就是最终的报文数据;
经过以上的大概讲解,相信大家对https有了更深入的认识,并且也能更好的理解为什么在实践https的时候要生成各种密钥和信任库了。
二、https协议实践
理解上面的相关原理后,我们就开始实现HttpsServlet来模拟简单登录接口,然后通过浏览器和app的访问该https接口;
1.服务端http实现
我们首先实现服务端http协议的get和post通信,项目的结构和主要实现代码如下:
HttpsServlet.java:
web.xml:
实现客户端登录的get和post请求,项目目录结构如下:
NextActivity.java:
activity_next.xml:AndroidManifext.xml:
启动服务器tomcat,运行客户端app效果如下:
启动Fiddler抓包如下,Get请求(Post请求可以自行实践)数据包如下,为明文传输!
接下来,我们就开始将当前http连接修改成https,并查看修改后的抓包情况。
2.生成密钥对、证书和信任证书库 (详情请查阅http://docs.oracle.com/javase/7/docs/technotes/tools/solaris/keytool.html)
在生成该操作过程中,我们将主要用Keytool工具:
keytool:是一个Java数据证书的管理工具,keytool将密钥(key)和证书(certificates)存在一个称为keystore的文件中;
keystore:在keystore里,包含两种数据:密钥实体(key entity)-密钥(secret key)又或者是公私钥密钥对、可信任的证书实体(trusted certificate entries)-只包含公钥;
生成服务器证书库
-genkey:创建一个新的密钥;
-alias:密钥别名,每个keystore都关联一个独一无二的别名;
-keyalg:使用的加密算法,使用RSA;
-keystore:密钥存储目录,保存在D:\ssl目录下;
-dname:
CN(Common Name名字与姓氏)
OU(Organization Unit组织单位名称)
O(Organization组织名称)
L(Locality城市或区域名称)
ST(State州或省份名称)
C(Country国家名称)
-storepass:存取密码,这个密码供系统从keystore文件取信息的时候使用;
-keypass:私有密钥的密码;
-validity:有效期,365天;
注意1:生成服务端密钥时,alias必须为tomcat,否则后续启动tomcat服务的时候会报错Caused by: java.io.IOException: Alias name tomcat does not identify a key entry ;
注意2:生成服务端密钥库时,CN必须与服务端的域名或者ip地址相同,否则正常获取证书访问;
从服务器证书库中导出服务器证书
生成客户端信任证书库 (由服务端证书生成的证书库)
注意3:-storetype BKS,是Android上面可以识别的格式。如果不指定,jdk默认生成的格式是JKS。 -provider org.bouncycastle.jce.provider.BouncyCastleProvider,需要下载jar包bcprov-jdk16-146.jar放到JDK_HOME\jre\lib\ext\目录下。 注意需要java1.6,其他的版本android下面有版本不匹配的问题;
生成客户端证书库
从客户端证书库中导出客户端证书
生成服务端信任证书库 (使得服务器信任客户端证书)
查看证书库中的全部证书 (服务器密钥库,客户端密钥库和信任库)
运行完成后,D:\ssl\目录下生成如下文件:
qproject.cer:客户端证书;
qproject.p12:客户端密钥;
qproject.truststore:客户端信任证书库;
tomcat.cer:服务端证书;
tomcat.keysotre:服务端密钥和信任证书库;
3.Tomcat的配置 (详细请查阅:https://tomcat.apache.org/tomcat-9.0-doc/ssl-howto.html)
修改tomcat的配置文件${catalina.base}/conf/server.xml;
port:https访问的端口;
SSLEnabled:true,开启https服务;
scheme:https;
secure:true,开启服务端安全通信,客户端获取服务器端证书;
keystoreFile:D:\ssl\tomcat.keystore;
keystorePass:123456,服务器证书库密码;
clientAuth:true,开启验证客户端;
sslProtocol:TLS,使用的协议;
truststoreFile:D:\ssl\tomcat.keystore,服务器证书库(已导入客户端证书) ;
truststorePass:123456;
提示1:启动tomcat服务器,报错如下:
Caused by: java.io.IOException: Alias name tomcat does not identify a key entry
at org.apache.tomcat.util.net.jsse.JSSEUtil.getKeyManagers(JSSEUtil.java:306)
at org.apache.tomcat.util.net.AbstractJsseEndpoint.initialiseSsl(AbstractJsseEndpoint.java:90)
at org.apache.tomcat.util.net.NioEndpoint.bind(NioEndpoint.java:245)
at org.apache.tomcat.util.net.AbstractEndpoint.init(AbstractEndpoint.java:839)
at org.apache.coyote.AbstractProtocol.init(AbstractProtocol.java:558)
at org.apache.coyote.http11.AbstractHttp11Protocol.init(AbstractHttp11Protocol.java:65)
at org.apache.catalina.connector.Connector.initInternal(Connector.java:1010)
... 13 more
处理1:检查你生成的服务器证书的-alias是否为tomcat
由于我们是在本机测试,并且在生成证书的时候CN配置了www.qserver.com,故我们在测试之前添加Hosts配置如下;
启动tomcat服务器,我们先用浏览器以get的方式测试下服务端https接口功能。 访问成功!服务器接口修改完毕,接下来我们来修改客户端;
提示2:初次访问接口时,会出现如下错误:
处理2:由于服务器Https握手过程中,交换的证书不在浏览器信任的范围,故提示错误。
Internet选项->内容->证书->受信任的根证书颁发机构->导入->tomcat.cer->存入受信任的根证书颁发机构->确认安装此证书;
4.客户端修改
添加项目目录asset,并在该目录下添加服务端验证客户端的证书qproject.p12,和客户端验证服务端的信任证书库qproject.truststore;
添加客户端https身份验证等相关逻辑;
HttpsHelper.java:
NextActivity.java: 修改获取HttpsURLConnection的方式,和域名https,其它不变
提示1:在请求https接口的时候,报错如下:
11-06 17:53:36.244 32662-5351/com.qunar.home W/System.err: java.io.IOException: Wrong version of key store.
11-06 17:53:36.245 32662-5351/com.qunar.home W/System.err: at com.android.org.bouncycastle.jcajce.provider.keystore.bc.BcKeyStoreSpi.engineLoad(BcKeyStoreSpi.java:805)
11-06 17:53:36.245 32662-5351/com.qunar.home W/System.err: at java.security.KeyStore.load(KeyStore.java:590)
11-06 17:53:36.245 32662-5351/com.qunar.home W/System.err: at com.qunar.hotel.ssl.HttpsHelper.getSSLContext(HttpsHelper.java:46)
11-06 17:53:36.245 32662-5351/com.qunar.home W/System.err: at com.qunar.hotel.ssl.HttpsHelper.getHttpsURLConnection(HttpsHelper.java:87)
11-06 17:53:36.245 32662-5351/com.qunar.home W/System.err: at com.qunar.hotel.NextActivity.doLoginGet(NextActivity.java:83)
11-06 17:53:36.245 32662-5351/com.qunar.home W/System.err: at com.qunar.hotel.NextActivity.access$300(NextActivity.java:27)
11-06 17:53:36.245 32662-5351/com.qunar.home W/System.err: at com.qunar.hotel.NextActivity$2$1.run(NextActivity.java:67)
11-06 17:53:36.245 32662-5351/com.qunar.home W/System.err: at java.lang.Thread.run(Thread.java:818)
处理:android系统只支持JKS默认证书格式,支持BKS,故生成客户端证书的时候使用DKS格式生成,见上面章节;
提示2:在请求https接口的时候,报错如下:
11-06 18:52:53.154 21260-23016/com.qunar.home W/System.err: java.io.IOException: Hostname '192.168.1.103' was not verified
11-06 18:52:53.154 21260-23016/com.qunar.home W/System.err: at com.android.okhttp.Connection.upgradeToTls(Connection.java:205)
11-06 18:52:53.155 21260-23016/com.qunar.home W/System.err: at com.android.okhttp.Connection.connect(Connection.java:155)
11-06 18:52:53.155 21260-23016/com.qunar.home W/System.err: at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:282)
11-06 18:52:53.155 21260-23016/com.qunar.home W/System.err: at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:216)
11-06 18:52:53.155 21260-23016/com.qunar.home W/System.err: at com.android.okhttp.internal.http.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:391)
11-06 18:52:53.155 21260-23016/com.qunar.home W/System.err: at com.android.okhttp.internal.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:341)
11-06 18:52:53.155 21260-23016/com.qunar.home W/System.err: at com.android.okhttp.internal.http.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:509)
11-06 18:52:53.155 21260-23016/com.qunar.home W/System.err: at com.android.okhttp.internal.http.DelegatingHttpsURLConnection.getResponseCode(DelegatingHttpsURLConnection.java:105)
11-06 18:52:53.155 21260-23016/com.qunar.home W/System.err: at com.android.okhttp.internal.http.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:25)
11-06 18:52:53.155 21260-23016/com.qunar.home W/System.err: at com.qunar.hotel.NextActivity.doLoginGet(NextActivity.java:84)
11-06 18:52:53.155 21260-23016/com.qunar.home W/System.err: at com.qunar.hotel.NextActivity.access$300(NextActivity.java:27)
11-06 18:52:53.155 21260-23016/com.qunar.home W/System.err: at com.qunar.hotel.NextActivity$2$1.run(NextActivity.java:67)
11-06 18:52:53.155 21260-23016/com.qunar.home W/System.err: at java.lang.Thread.run(Thread.java:818)
处理:由于我们在测试环境,故请求url中使用了服务器的ip,到时和证书中的 CN(Common Name名字与姓氏)不匹配(在正式的环境不会有该问题)。那么我们默认跳过该认证或者在正式线使用线上的域名访问:
//忽略请求域名和证书域名的校验
connection.setDefaultHostnameVerifier( new HostnameVerifier(){
public boolean verify(String string,SSLSession ssls) {
return true;
}
});
5.tomcat修改
原来的connector配置只有加解密,现在加上服务端身份验证相关配置,修改server.xml文件如下:
clientAuth:启动客户端身份验证;
truststoreFile:服务端信任的客户端证书库;
truststorePass:信任证书库密码;
6.测试Https接口
安装app,并重新启动tomcat服务,使用Fiddler抓取https请求使用加密传输!
7.代码库
QProject:https://github.com/Pengchengxiang/QProject 分支:feature/https
QServer:https://github.com/Pengchengxiang/QServer 分支:feature/https