做过Android开发的同学,一定都有和服务端联调接口的经历,昨天才刚刚把接口调通,服务端同学“一不小心”又把接口的返回字段格式改了,一连串的崩溃就来了,跟代码跟了半天,原来是服务端下发的有个字段格式不对。这种排错的方式,效率异常的低。如果我们能够一开始就去check服务端下发的数据是否正确,就可以更加快速的定位问题。所以,抓包在客户端开发中,显得尤为重要。
在笔者的应用中,主要是抓HTTP/HTTPS的包,当然也有时候会抓TCP包。
常用的抓包工具有如下几种:
上面,是笔者使用比较多的抓包工具。
PS:
- Charles是收费软件,有钱的同学们建议购买正版。
- HTTPS的抓包与HTTP类似,只需要给手机装上
Charles
的证书就行(代码里面没有对证书进行校验才可喔。)
要能够抓到包,前提是你的手机与你的电脑要在同一个局域网上。然后将你手机的网络代理设置到你的电脑的ip上。
Fiddler 使用教程传送门
Charles 使用教程传送门
使用命令修改Android手机系统的配置,如下代码:
// 设置代理
adb shell settings put global http_proxy ip_address:port
// 移除代理
adb shell settings delete global http_proxy
adb shell settings delete global global_http_proxy_host
adb shell settings delete global global_http_proxy_port
移除代理需要重启手机方可生效,设置可直接多次覆盖,不需要移除
使用adb
来修改 settings中的值,修改的是系统的环境配置,你可以在项目中使用Java
代码获取到修改的值:
// 打印所有的属性
Properties properties = System.getProperties();
for (Map.Entry<Object, Object> property : properties.entrySet()) {
Log.d("TAG", property.getKey() + "=" + property.getValue());
}
// 仅读取代理host和post
System.getProperty("http.proxyHost"); // https.proxyHost
System.getProperty("http.proxyPort"); // https.proxyPort
那网络请求是怎么连接上代理设置的呢?
以OKHTTP为例:
// OkHttpClient.Builder
public Builder() {
// 初始化
proxySelector = ProxySelector.getDefault();
if (proxySelector == null) {
proxySelector = new NullProxySelector();
}
// 其它初始化操作省略
}
可以看到, 默认使用的是 ProxySelector.getDefault()
/**
* Supports proxy settings using system properties This proxy selector
* provides backward compatibility with the old http protocol handler
* as far as how proxy is set
*
* Most of the implementation copied from the old http protocol handler
*
* Supports http/https/ftp.proxyHost, http/https/ftp.proxyPort,
* proxyHost, proxyPort, and http/https/ftp.nonProxyHost, and socks.
* NOTE: need to do gopher as well
*/
public abstract class ProxySelector {
private static ProxySelector theProxySelector;
static {
try {
Class<?> c = Class.forName("sun.net.spi.DefaultProxySelector");
if (c != null && ProxySelector.class.isAssignableFrom(c)) {
theProxySelector = (ProxySelector) c.newInstance();
}
} catch (Exception e) {
theProxySelector = null;
}
}
public static ProxySelector getDefault() {
return theProxySelector;
}
}
可以看到,这个地方默认使用的是 DefaultProxySelector。
因为笔者公司的网络IP地址是动态的,每一次在手机系统里面的网络上修改代理,这是一个让人崩溃的事情,所以结合 0x03 中介绍的方式结合,自己写了一个脚本来获取ip地址,并重设代理:
#!/bin/bash
# 可以指定网卡,默认使用 en0
EN0=$1
if [ ! $EN0 ]; then
EN0="en0"
fi
echo "current network card:$EN0"
# 获取当前网卡的ip地址
ipAddress=`ifconfig $EN0 | grep 'inet ' | grep -v 127.0.0.1 | cut -d\ -f2`
echo "current ip address: $ipAddress"
echo "setting android devices global http_proxy:$ipAddress:8888"
echo " current shell:"
echo " adb shell settings put global http_proxy $ipAddress:8888"
# 使用settings设置的命令来设置代理
adb shell settings put global http_proxy "$ipAddress:8888"%