app常用框架(HttpsURLConnection)-(X509TrustManager)-(HostnameVerifier)
HttpsURLConnection
HttpsURLConnection 安卓自带的用于访问http访问 ,现在已经不怎么用了(还有一个是apache的库 这个已经在Android5.0已经被废弃了)
Okhttp 现在这个几乎是主流,百分之90都是基于这个去开发的或者是跟这个相关的库进行开发的,OKhttp是第三方的库,现在是okhttp3它也有okhttp的版本
conn.connect就会产生一个请求在通过输入流
其中需要注意的是这一句
这一句是设置ssl的通信组件的,这个sslContext组件是安卓自带的比较常用socketFactory,OKhttp里面的也是用的这个
这个类要在哪里调用,到类名按ctrl跟上去
SSlcontext组件通信有两种方法,这里就讲一种就够了,如果要过证书认证的话 这个东西完全可以自己写通信组件给他设置到connection里面.如果遇到的话只需要hook setSSlsocketFactory这个方法
那这个SSlcontext怎么来的呢,就是上面调用的getsslContext函数,那这个函数是自己写的,按住ctrl跟上去
这里呢有个X509的信任证书管理器,用处就是信任证书和校验的
X509TrustManager
X509TrustManager实例化之后要实现三个方法
正常流程是:
我们要得到一个正常能够用于访问https的sslcontext的话,就要自己实例化一个X509TrustManager,然后需要将他设置到sslcontext初始化的地方,设置进去
然后sslcontext可以去获取一个单例这个getInstance指明是TLS,指明SSL也可以,都是同一个东西
得到一个context不能直接用,还需要做一步初始化的动作 就是138行
然后才可以一个SocketFactory去用于通信
那说白了只有三个步骤
获取单例,初始化,在去获取socketFactory,设置到这个urlconnection里面就可以了
那在初始化 需要给他传三个参数,那这三个参数上实际都是可空的,但如果要做一些证书校验的话这三个参数是不能空的,一般都是怎么写,第一个是给keyston就是一个证书的库 生成证书是有个keystone的 但对我们不影响因为不自己生产证书,所以这里面只需要定义第二个就可以了 就是{trustManager}
如果说你是像我怎么写的话 就代表信任所有证书
如果说要校验服务端证书的话 就需要在第一个server下面去进行校验,这个在http调用的时候会自动调用这个函数的
简单点说就是你去实例化X509TrustManager之后,你需要直接去实现这三个方法,当你去进行这个连接访问时候,他会自动调用checkServerTrusted这个,然后给你传进来两个内容 一个是证书链 一个是算法名字 通常是RSA
证书链 传进去是两个证书不是三个,因为服务器去配置的时候不会去配置这个根证书,根证书的话一般在证书库里面直接就有,所以配置的时候是配置前面两个
当你访问百度的时候,X509Certificate获取的长度是2 服务器不配置根证书,可以在这个方法中去做证书校验
checkClientTrusted用于客户端校验,一般没什么用
所有者校验,这个现在至少很少看到有人去弄这个,基本上都是https能用起来就可以了,如果真的要校验一般会去checkServerTrusted
checkServerTrusted主要是 证书链的校验如 证书是否过期, 具体可以校验什么? 我展开给你们看看
大体的逻辑应该都差不多了,在说一次Https访问的时候除了正常访问之外,我们通常会设置两个东西
一个是setSSLSocketFactory 通信组件
第二个是setHostnameVerifier 域名校验 (后面介绍)
设置通信组件的时候通常也是怎么几个步骤
一个是设置sslContext的单例然后在初始化,初始化完事之后直接会得到SocketFactory然后在设置在conn.setSSLSocketFactory里面,这样就可以进行https的访问了
如果要进行域名证书校验的话就要去trustManager,实例化完之后X509TrustManager必须要去实现他这三个方法,额 至少是两个checkServerTrusted,checkClientTrusted
如果里面没有写任何代码的话,默认信任所有证书,如果说要做单向验证的话,就在checkServerTrusted下写你的验证代码
比如X509Certificate[] chain 传入的是证书链是一个数组是吧,那就会吧百度这两个证书传进来,然后在里面做一些校验
那这里呢 看下我是怎么做校验的
那这里怎么进行公钥比对呢,这里有两个方法
1将1.cer打开复制到certificate
2.直接拖到assets目录下,两种方法都可以,我这里用的第一个写在这里面的然后你把证书的公钥解析出来
这是公钥验证,这里还可以在做一个校验就是时间
然后还可以在输出证书的一些信息
当然在X509Certificate里面有很多方法,可以做到一个证书有多少内容你就可以解析多少内容,这个就各位去了解
HOOK:那首先要写一个信任所有证书的sslcontext,然后Hook conn.setSSLSocketFactory,设置成自己的sslContext.getSocketFactory
HostnameVerifier
HostnameVerifier域名验证,上面说的是证书,这里讲的是域名
一般会去设置不校验域名直接返回真(True)
Hook的话 就是直接传上图中的内容域名校验就过了(图中代码用的自己写的Demo)
Hook点为这两个方法
那如何去编写他
我们看他类型是HostnameVerifier 那这里就需要实例一个HostnameVerifier,这个里面需要重写一个verify()方法
到时候会将Hostname 传进来 就是当前证书的hostname
那这里呢就可以做域名的验证,如果不是baidu.com 就报错
我们这里将App安装上并且代理,并打开抓包工具Fd,此时可以看到抓包工具无请求,并且logcat日志请求为Null
签发者已经变成fd的证书,在这里公钥验证就已经失败了,
如果我们把校验那块全部删除,在请求
总结:
如果说要Hook文章中的情况。就需要Hook如下两个方法
1.Hook verify()
2.Hook checkServerTrusted()