实际问题场景描述
使用dio框架发起的网络请求,手机上都配置好一切后,Charles却没法抓到包。
问题分析
需要知识储备:https的ssl加密实现、charles抓https包的原理
问题原因
- Flutter应用中常用的HTTP客户端库(如Dio或http)是独立使用Dart语言的HTTP实现,未直接使用系统级的网络堆栈,所以它们不会自动继承系统代理配置,因此系统上的代理配置无法生效。
- 在Dart/Flutter中,也就是框架层面,默认的HTTP客户端不信任自签名证书,网络库(如Dio或http)层继承了这个默认配置。
问题解决
需在dart代码内,手动指定代理ip和端口。(可以自己写一个简单的小页面,来配置代理,指定代理端口和ip)
如果使用的是dio库,如下
dio!.httpClientAdapter = IOHttpClientAdapter(
createHttpClient: () {
final client =
HttpClient(context: SecurityContext(withTrustedRoots: false));
client.findProxy = (uri) {
return 'PROXY $proxyIp:$proxyPort'; // proxyIp: 代理ip,proxyPort:代理端口
};
client.badCertificateCallback =
(X509Certificate cert, String host, int port) => true; // 允许自签名证书
return client;
},
);
如果使用的是Http库,如下
HttpClient client = HttpClient();
client.findProxy = (uri) {
return "PROXY $proxyIp:$proxyPort"; // proxyIp: 代理ip,proxyPort:代理端口
};
client.badCertificateCallback = (X509Certificate cert, String host, int port) => true; // // 允许自签名证书
提问
为什么Flutter的dio不支持类似安卓/iOS原生应用一样直接被抓包?
- SSL Pinning:Flutter 默认情况下没有启用 SSL Pinning,但它会对 SSL 证书进行验证。抓包工具通常通过代理和自签名证书来解密 HTTPS 流量,因此需要忽略 SSL 证书错误才能进行抓包。
-
网络库的行为:Flutter 使用
dart:io
库进行网络请求,该库在进行 HTTPS 请求时会验证服务器的 SSL 证书。 - 中间人攻击防护:忽略 SSL 证书错误可能会让应用暴露于中间人攻击,因此只应在开发和调试时使用,在生产环境中绝对不要忽略 SSL 证书错误。
- 在Flutter应用中不配置代理,网络请求默认不会走系统代理,这是因为Flutter的网络请求使用了独立的网络库(如
dart:io
),而不是依赖操作系统的网络堆栈
总结:
- Flutter对SSL证书的验证更严格,而charles使用的不是受信任机构颁发的证书,所以在验证SSL证书的时候报错了
- 对比iOS来说,AFNetworking会依赖操作系统提供的信任机制来验证 HTTPS 请求的安全性,而flutter没有依赖系统信任机制。
网友评论