集成方法:
flutter_packet_capture: ^1.0.0
//scheme配置
Packetcapture.setConfig(schemeConfig: 'capture://',modeConfig: "debug");
Packetcapture.initUniLinks(callBack: (hostPort){
//設(shè)置代理
Network.setHttpProxy(hostPort);
});
抓包的三種方法:
方法一:直接在dio里面設(shè)置ip以及端口(缺點(diǎn):代理只能寫死粹污,不靈活)
(_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和代理端口(缺點(diǎn):安卓好像無法獲入剐凇)
ios原生代碼:
//自動獲取手機(jī)代理
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協(xié)議的方式傳入代理ip和代理端口(完美解決iOS,安卓抓包問題)
1,注冊自己的URL Scheme寓盗,例如:scheme://
2叮阅,定義參數(shù)規(guī)則,例如:scheme://xxxx?host=10.0.206.163&port=8888 (port可不要龄句,默認(rèn)8888)
3回论,flutter監(jiān)聽解析參數(shù),并在dio里面設(shè)置代理
4分歇,使用草料生成一個(gè)二維碼:內(nèi)容:scheme://xxxx?host=10.0.206.163
然后使用原生相機(jī)掃碼進(jìn)入app就可以抓包啦傀蓉,這里需要注意需要先打開app再掃碼進(jìn)入app才行
flutter代碼:
Future<Null> initUniLinks() async {
// 監(jiān)聽插件scheme數(shù)據(jù)
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"){//設(shè)置抓包代理
String host = dict["host"];
String port = dict["port"];
//這里是網(wǎng)絡(luò)請求封裝
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 要處理的業(yè)務(wù)類型
String getTypeStr(String link){
List params = link.split("?");
String typeStr = params[0];
typeStr = typeStr.replaceAll("scheme://", "");
return typeStr;
}
//url參數(shù)轉(zhuǎn)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;
}
Net里面的關(guān)鍵代碼
//設(shè)置代理
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;
}
如有更好的辦法請指正