记一次手机本地时间修改引起的https请求失效的bug分享

灵异bug发生

某天广州银行直销银行APP在做兼容性测试的时候,用一个很久不用的的手机(三星 SM-C101)进行测试,发现app无法使用,提示网络异常。但是手机却是满格wifi,也没有设置代理,查看手机系统也是Android 4.2以上的(我们的产品支持的API是14以上,讲道理的话手机系统肯定也是支持的),但是的确每个页面都toast提示“网络连接异常”,实在是诡异。

bug问题排查

先看下网络是不是ok的吧,万能ping百度,百度能访问,说明我们的网络肯定是通的。只好抓包进一步看看是不是后端环境返回的网络异常,但是抓包工具上并没有抓到https请求,进一步地可以排除后端问题。此时非常困惑,为什么百度这些可以使用而我们的APP却无法访问网络呢,然后看了一下我们公司开发的同类的app紫金银行,也是无法使用网络,首先想到的会不会是兼容性问题,想了好久,网上也搜了好久,都没有找到这款旧手机相关的特别信息,历史bug列表也没有改款手机有过类似的bug。最后突然注意到了手机时间,手机时间是2015年1月1日,原来手机时间不知道被谁设置到2015年去了,2015年我们的app还未问世呢,我们APP使用的是https协议,如果手机修改了本地时间,自然是无法访问网络了!

bug引入原因

修改本地时间后,手机为什么https请求失效呢
所以https与本机时间有什么关系呢?
先来了解什么是https协议
HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,要比http协议安全。
为了便于理解记忆,有个著名的小故事。

第一话:古代某国边塞驻扎着10万大军。一日,狼烟四起,外敌来犯,为平息叛乱,皇帝派遣A将军去平息边关战事,临行前,皇帝给A将军一行送行,将一枚敕造铜质虎符的一半交与将军,说道:“虎符合并时,边关10万大军,凭此全符调遣,见符如见寡人,切记妥善保管,不可有丝毫缺损。”【对应图中3过程】
第二话: 数日后,A将军抵达边塞大营,驻地B将军再三确认A将军身份,于是乎要求A将军拿出另一半虎符进行拼对,虎符无缝隙对接,确系A将军是皇帝派来的“定边大将”,可与B将军共同统领10万大军。【对应图中1、2、3过程】
第三话:边关大军与来犯敌军两军对阵,排兵布阵通过鼓声号令,重鼓三声,大军前进30步,急鼓5声,方阵变换,骑兵出击,步兵合围。两军展开了激烈的对战……【对应图中5、6过程】


https过程-引用.png

https与本机时间关系
https协议与本机时间相关,https传输的过程中是加密的,而加密的证书里面是携带有效期的,证书的有效期是一个固定的时间段。设备进行https连接的时候,是会携带当前的时间(本机时间)。如果时间不在这个有效期之内,https链接建立的时候,就会报网络无法连接的错误。

问题解决

解决方法1:修改本地手机时间

知道原因后就好解决了,将手机时间设置为随网络时间设定,也就是符合现在的时间。所有的app都可以正常使用了。

但是这个方法有点鸡肋,如果用户手机出现了这类问题,只能通过用户自己去发现问题再设置时间解决问题,用户都是懒的并且基本上是无IT相关知识的,基本上不太可能去排查问题的原因,此时则会面临这类用户的流失。

解决方法2:在代码里面捕获异常,并返回异常提示

如果在使用https证书导入时默认配置验证通过所有链接,这肯定是不安全的,但是某些手机由于内部时间并不是正常时间,在https证书的有效时间外,创建连接时,只想避免这一点时可以捕获时间验证的异常,使其不报错,能正确告诉用户是这是哪一类异常

例如:
(1)此异常是证书已经过期异常,在手机调到证书生效时间之后会捕捉到此异常,提示用户证书已过期
(2)此异常是证书未生效异常,在手机调到证书生效时间之前会捕捉到此异常,提示用户手机当前时间与证书生效时间不符,请调整手机时间

public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
              if (chain != null)
                  for (X509Certificate cert : chain) {
                      try {
                          // Make sure that it hasn't expired.
                          cert.checkValidity();
                      } catch (CertificateExpiredException e) {
                          //此异常是证书已经过期异常,在手机调到证书生效时间之后会捕捉到此异常
                          L.w(TAG, "checkServerTrusted: CertificateExpiredException:" + e.getLocalizedMessage());
                      } catch (CertificateNotYetValidException e) {
                          //此异常是证书未生效异常,在手机调到证书生效时间之前会捕捉到此异常
                          L.w(TAG, "checkServerTrusted: CertificateNotYetValidException:" + e.getLocalizedMessage());
                      }
                      try {
                          // Verify the certificate's public key chain.
                          cert.verify(cert.getPublicKey());
                      } catch (CertificateExpiredException e) {
                          //此异常是证书已经过期异常,在手机调到证书生效时间之后会捕捉到此异常
                          L.w(TAG, "checkServerTrusted: CertificateExpiredException:" + e.getLocalizedMessage());
                      } catch (CertificateNotYetValidException e) {
                          //此异常是证书未生效异常,在手机调到证书生效时间之前会捕捉到此异常
                          L.w(TAG, "checkServerTrusted: CertificateNotYetValidException:" + e.getLocalizedMessage());
                      } catch (CertificateException ex) {
                          //其他异常正常报错
                          L.w(TAG, "Throw checkClientTrusted: " + ex.getLocalizedMessage());
                          throw ex;
                      } catch (NoSuchAlgorithmException e) {
                          L.w(TAG, "checkServerTrusted: NoSuchAlgorithmException:" + e.getLocalizedMessage());
                      } catch (InvalidKeyException e) {
                          L.w(TAG, "checkServerTrusted: InvalidKeyException:" + e.getLocalizedMessage());
                      } catch (NoSuchProviderException e) {
                          L.w(TAG, "checkServerTrusted: NoSuchProviderException:" + e.getLocalizedMessage());
                      } catch (SignatureException e) {
                          L.w(TAG, "checkServerTrusted: SignatureException:" + e.getLocalizedMessage());
                      }
                  }
          }

问题解决后带来的启发

这个问题定位的时间过长且曲折,主要是因为测试对https协议工作原理不了解,所以作为测试童鞋,需要对网络协议原理、技术实现原理、网络基础知识都得掌握理解,才能在遇到问题的时候快速定位问题,并驱动开发解决之。

另外,一个困扰自己超过2个小时的问题有必要整理下来,积累多了也是一份宝贵的财富,yeah!

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,098评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,213评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,960评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,519评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,512评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,533评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,914评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,804评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,563评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,644评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,350评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,933评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,908评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,146评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,847评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,361评论 2 342

推荐阅读更多精彩内容