当前位置: 首页 > news >正文

flutter 专题 六十六 Flutter Dio包网络请求抓包解决方案

在Flutter中进行网络请求时,我们可以使用的库有3个,即Http请求库、HttpClient请求库和Dio请求库(详细介绍请参考:Flutter开发之Http网络请求),使用得最多的就是Dio请求库。因为相比Http请求库和HttpClient请求库,Dio库不仅支持常见的网络请求,还支持Restful API、FormData、拦截器、请求取消、Cookie管理、文件上传/下载、超时等操作。

不过,默认情况下,Dio进行网络请求时是不支持抓包的,所以如果要进行抓包,就需要对Dio进行请求封装,并编写代理代码。下面是代理的几种写法:

方法一

我们可以直接在Dio里面设置ip以及端口,通过硬编码的方式进行代理,代码如下:

(_dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate =(client) {//这一段是解决安卓https抓包的问题client.badCertificateCallback =(X509Certificate cert, String host, int port) {return Platform.isAndroid;};client.findProxy = (uri) {return "PROXY 代理ip:代理port";};};

不过,这种硬编码方式,写得太死,不够灵活,每次更改代理都需要打包。

方法二

直接在原生插件获取手代理ip和代理端口,不过Android比较难,下面是iOS的实现。

 //自动获取手机代理NSDictionary *proxySettings = (__bridge NSDictionary *)(CFNetworkCopySystemProxySettings());NSArray *proxies = (__bridge NSArray *)(CFNetworkCopyProxiesForURL((__bridge CFURLRef _Nonnull)([NSURL URLWithString:call.arguments]), (__bridge CFDictionaryRef _Nonnull)(proxySettings)));NSString *hostName = proxySettings[@"HTTPSProxy"];NSString *portName = [NSString stringWithFormat:@"%@",proxySettings[@"HTTPPort"]];long HTTPEnable = [proxySettings[@"HTTPEnable"] longValue];if (HTTPEnable==0) {hostName = @"";}
方法三

除了上面的硬编码方式外,我们还可以采用scheme协议的方式传入代理ip和代理端口。此方法的步骤如下:
1,注册自己的URL Scheme,例如:scheme://
2,定义参数规则,例如:scheme://tiaoshi?host=10.0.206.163
3,引入flutter插件:uni_links: ^0.2.0
4,flutter监听解析参数,并在dio里面设置代理
5,使用[草料]https://cli.im生成一个二维码:内容:scheme://tiaoshi?host=10.0.206.163
6,使用原生相机扫码进入app就可以抓包

下面是涉及的代码,Flutter代码如下:

Future<Null> initUniLinks() async {// 监听插件scheme数据getLinksStream().listen((String link) {link =  Uri.decodeComponent(link);if(link.contains("scheme://")){String type = getTypeStr(link);String param = link.replaceAll("scheme://$type?", "");Map dict = getUrlParams(param);if(type=="tiaoshi"){//设置抓包代理String host = dict["host"];String port = dict["port"];//这里是网络请求封装Net.setHttpProxy(host,port==null?"8888":port);}}// Parse the link and warn the user, if it is not correct}, onError: (err) {// Handle exception by warning the user their action did not succeed});}//获取scheme 要处理的业务类型String getTypeStr(String link){List params = link.split("?");String typeStr = params[0];typeStr =  typeStr.replaceAll("scheme://", "");return typeStr;}//url参数转mapMap getUrlParams(String paramStr) {Map map = Map();List params = paramStr.split("&");for(int i=0;i<params.length;i++){String str = params[i];List arr = str.split("=");map[arr[0]]= arr[1];}return map;}

代理层代码:

static void setHttpProxy(String host,String port) {Application.httpProxy = host+':'+port;_initDio();}static Future<void> _initDio() async {DeviceInfoPlugin deviceInfo = DeviceInfoPlugin();if (Platform.isAndroid) {_androidInfo = await deviceInfo.androidInfo;} else if (Platform.isIOS) {_iosInfo = await deviceInfo.iosInfo;}_dio = Dio(BaseOptions(contentType: 'application/json',baseUrl: Config.BASE_URL,));_dio.options.receiveTimeout = 5000;_dio.options.connectTimeout = 10000;if (Application.httpProxy.length != 0) {(_dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate =(client) {//这一段是解决安卓https抓包的问题client.badCertificateCallback =(X509Certificate cert, String host, int port) {return Platform.isAndroid;};//这是抓包代理client.findProxy = (uri) {return "PROXY ${Application.httpProxy}";};};}_dio.interceptors.addAll([InterceptorsWrapper(onRequest: (Options options) {options.headers['DeviceName'] = 'xxxx';return options;},onResponse: (Response res) {try {...return res;} catch (e) {return res;}},onError: (DioError e) {print(e);}break;default:}return e;},),]);}static Future<ResponseModel> get(String path, {Map<String, dynamic> queryParameters,Options options,CancelToken cancelToken,void Function(int, int) onReceiveProgress,}) async {if (_dio == null) {await _initDio();}final res = await _dio.get<ResponseModel>(path,queryParameters: queryParameters,options: options,cancelToken: cancelToken,onReceiveProgress: onReceiveProgress,);return res.data;}static Future<ResponseModel> post(String path, {dynamic data,Map<String, dynamic> queryParameters,Options options,CancelToken cancelToken,void Function(int, int) onSendProgress,void Function(int, int) onReceiveProgress,}) async {if (_dio == null) {await _initDio();}final res = await _dio.post<ResponseModel>(path,data: data,queryParameters: queryParameters,options: options,cancelToken: cancelToken,onSendProgress: onSendProgress,onReceiveProgress: onReceiveProgress,);return res.data;}

相关文章:

  • 《马尼拉》桌游期望计算器
  • 240422 leetcode exercises
  • 2025高频面试算法总结篇【其他】
  • ADB->查看某个应用的版本信息
  • 性能比拼: Nginx vs Apache
  • vdso内核与glibc配合的相关逻辑分析
  • IDEA打不开、打开报错
  • 【Easylive】手动实现分布式事务解决方案流程解析
  • 【Flask】Explore-Flask:早期 Flask 生态的实用指南
  • 多模态大语言模型arxiv论文略读(三十三)
  • 【产品经理思维】
  • 多级缓存架构,让系统更快的跑起来!
  • 特伦斯智慧钢琴评测:如何用科技重塑钢琴学习新体验
  • Cribl 利用表向event 中插入相应的字段-example-01
  • C++入门语法
  • FreeRTOS中的优先级翻转问题及其解决方案:互斥信号量详解
  • 第十四届蓝桥杯 2023 C/C++组 平方差
  • 设计模式 建造者模式
  • Pycharm(九)函数的闭包、装饰器
  • compat-openssl10和libnsl下载安装
  • 马文化体验展商圈启动,环球马术冠军赛的能量不止在赛场
  • 针对“二选一”,美团再次辟谣
  • 云南昭通一公园发现毒饵,多只宠物狗疑中毒致死
  • 泽连斯基称乌克兰全境响起防空警报
  • 海康威视:去年海外主业和机器人等创新业务占比首次超50%
  • 第八届进博会倒计时200天,超100家展商将连续八届参展