Flutter Dio包网络请求抓包解决方案
2020/8/17 14:04:05
本文主要是介绍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参数转map Map 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; }
这篇关于Flutter Dio包网络请求抓包解决方案的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2022-10-05Swift语法学习--基于协议进行网络请求
- 2022-08-17Apple开发_Swift语言地标注释
- 2022-07-24Swift 初见
- 2022-05-22SwiftUI App 支持多语种 All In One
- 2022-05-10SwiftUI 组件参数简写 All In One
- 2022-04-14SwiftUI 学习笔记
- 2022-02-23Swift 文件夹和文件操作
- 2022-02-17Swift中使用KVO
- 2022-02-08Swift 汇编 String array
- 2022-01-30SwiftUI3.0页面反向传值