一、前言
作为一个移动应用开发者,我们在平时的应用开发过程中,除了UI界面的相关编码之外,做的最多的编码工作就是和服务端程序员进行接口的联调;当然在接口联调的过程中,往往会出现接口调试不通的情况,可能是我们确实没有按照接口文档的要求来进行接口请求,如没有按照指定的请求方式Post/Get,请求头Header,Content-Type,或者请求参数等来进行正确的接口请求 ,当然也有可能是服务端程序本身的问题,为了快速定位我们请求是否是有问题,我们可以通过一些抓包工具Wireshare、Charles等来对我们发出的请求进行抓包,以此来查看接口请求的各项配置是否是正确的;本篇文章介绍一下Charles抓包的流程;
二、Charles抓包
1.下载安装Charles
下载地址:https://www.charlesproxy.com/download/
下载之后正常安装即可,安装完成成后,打开程序后主界面如下图所示
2.1 设置Charles允许代理HTTP请求
Charles中->Proxy->Proxy Setting 中设置代理的端口号为8888,并且勾选允许代理HTTP请求,如图所示
2.2 Android 设备端相关设置
(1)首选将Android设备连入与电脑相同网络,如同一WIFI;
(2)设置手机的代理
打开手机的WIFI列表,点击已连接的WIFI,找到代理设置,设置主机名为
电脑的IP地址,电脑的IP地址可以在CMD窗口中通过ipconfig查看,也可以在Charles中Help->Local IP Address中查看;设置代理的端口号8888,如下图所示
Android设备设置过代理之后,电脑上的Charles就可以抓取Android设备上的HTTP请求了,并且可以查看到HTTP请求的完整请求配置,请求方式,Header,Content-Type,请求的参数等
如图所示,我在手机浏览器中输入了一个HTTP请求接口,Charles成功抓取到了
但是仅仅这样设置,只能成功抓取HTTP请求,不能够抓取HTTPS请求,或者准确的说是抓取到HTTPS请求,但是无法查看到具体的请求配置,如请求参数等,会出现unknow的情况;
2.3 抓取HTTPS请求包
2.3.1 电脑上安装Charles证书
help —> SSl Proxying —> install charles root certificate —> 安装证书
2.3.2 设置SSL Proxying
Proxy —> SSL Proxy Settings —> 然后add操作,host设置为*表示所有, Port设置为443
这样设置之后,如果Android设备的系统版本在Android 7.0之前,是可以正常抓HTTPS包的,但是Android 7.0开始是无法正常抓HTTPS包的,在Android 7.0以上应用内请求HTTPS接口会报错
java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
对于Android 7.0及以上的设备还需要进行如下操作
2.4 Android 7.0及以上设备HTTPS抓设置
2.4.1 Android设备上安装Charles证书
(1)Android 设备下载Chales证书
手机上浏览器输入chls.pro/ssl,下载Charles证书,下载下来的证书如果后缀名不是.crt,需要将证书后缀名修改成.crt,然后保存到SD卡下某个目录中,我这里保存到了SD卡根目录下
设置->系统安全->加密凭据->安装证书->CA证书 然后找到之前下载的Charles证进行安装;
安装之后,在设置->系统安全->加密凭据->信任的凭据->用户中可以看到我们安装的Charles证书
在Android 7.0开始引入了Network Security Configuration的安全功能。这个新功能允许开发人员在不修改应用程序代码的情况下自定义他们的网络安全设置。如果应用程序运行的系统版本高于或等于Android 7.0(API 24),并且targetSdkVersion>=24,则只有系统(system)证书才会被信任。所以用户(user)导入的Charles根证书是不被信任的。
我们在项目res目录下新建一个xml目录,然后新建一个network_security_configuration文件,内容如下
<network-security-config>
<base-config cleartextTrafficPermitted="true">
<trust-anchors>
<certificates
overridePins="true"
src="system" />
<certificates
overridePins="true"
src="user" />
</trust-anchors>
</base-config>
</network-security-config>
然后在AndroidManifest.xml的Application标签下通过android:networkSecurityConfig属性使用
<application
android:name=".constant.LocalApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.KotlinDemo"
android:networkSecurityConfig="@xml/network_security_config"
>
....
</application
至此就可以正常在电脑的Charles中抓取Android设备应用中的HTTPS请求了
我们给Android设备连接的WIFI设置了代理,这个代理的IP是与Android设备同一网络的PC电脑,而Charles是运行在这个PC电脑上,并且设置了Charles可以代理 电脑上的HTTP请求,所以Charles也就变成了Android设备的HTTP请求代理服务器,Android设备上的所有HTTP请求都会经过Charles;
实际的过程是Android设备上的HTTP请求,都会被Charles截获到,然后Charles伪装成客户端与HTTP请求的服务端进行通信,服务端处理后返回的结果也会先经过Charles,然后Charles再将返回的结果返回给Android客户端;
结合HTTPS请求过程来描述Charles抓包原理:
1.客户端发送的请求经过Charles,Charles截获客户端请求伪装成客户端和
服务端建立连接(HTTPS连接握手过程)
2.服务端会返回数字证书给客户端,这个时候数字证书也是先到达Charles,
Charles用根证书的公钥解密出数字证书,数字证书中包括了(服务端返回的非对称加密公钥,以及证书颁发给,颁发者,过期时间等信息)
3.Charles用自己的数字证书替换服务端的数字证书,然后返回给客户端
4.然后客户端就按照正常的HTTPS请求过程,因为我们在Android设备上安装了Charles证书,所以可以正常解密出Charles发送过来的数字证书,所以可以正常获得服务器发过来的非对称加密的公钥; 客户端就正常生成一个对称加密的秘钥,对请求数据进行加密,然后使用解密出来的服务端非对称加密的公钥对生成的对称加密的秘钥进行加密,然后发送给服务器
5.这个时候Charles又截获了客户端发过来的加密后的请求数据,由于Charles之前获取到了真正服务端的私钥,所以是可以解密出客户端的对称加密秘钥以及请求数据,所以可以显示出HTTPS请求数据给抓包者看,Charles会将截获的客户端请求发给服务端
6.服务端收到Charles发出来的请求,解密出对称加密秘钥,然后解密出请求数据,处理后,返回的结果数据使用解密出来的对称加密秘钥加密,然后返回
7.Charles收到服务端的返回结果,同样的由于之前获取到对称加密秘钥,所以可以解密出返回数据显示出来给抓包者看;然后Charkes会将服务端的返回结果返回给客户端;
这样Charles就作为中间代理者,可以抓取到整个客户端与服务端的通信过程
欢迎扫码订阅公众号,公众号主要分享原创或转载移动开发技术文章,和广大移动开发者一起学习成长!