如何在Flutter/Ionic的Webview中监听HTTP请求并获取POST载荷?
监听Flutter/Ionic WebView内的HTTP请求(无需修改源HTML)
Flutter 实现方式
要捕获WebView内的POST请求载荷,无需修改源HTML的核心思路是在页面加载完成后注入JavaScript脚本,拦截XMLHttpRequest和Fetch API的调用,再通过Flutter的JavaScriptChannel将数据回传到原生层。
代码示例
使用webview_flutter插件实现:
import 'package:flutter/material.dart'; import 'package:webview_flutter/webview_flutter.dart'; class RequestCapturingWebView extends StatefulWidget { final String targetUrl; const RequestCapturingWebView({super.key, required this.targetUrl}); @override State<RequestCapturingWebView> createState() => _RequestCapturingWebViewState(); } class _RequestCapturingWebViewState extends State<RequestCapturingWebView> { late final WebViewController _webController; @override void initState() { super.initState(); _webController = WebViewController() ..setJavaScriptMode(JavaScriptMode.unrestricted) // 创建JS通信通道,用于接收WebView传来的请求数据 ..addJavaScriptChannel( 'RequestCaptureChannel', onMessageReceived: (JavaScriptMessage message) { // 解析捕获到的请求数据,这里可以对接你的注册逻辑 final requestData = message.message; print('捕获到POST请求数据: $requestData'); // 示例:解析JSON提取载荷 // final payload = jsonDecode(requestData)['payload']; }, ) ..loadRequest(Uri.parse(widget.targetUrl)) ..setNavigationDelegate( NavigationDelegate( onPageFinished: (String url) { // 页面加载完成后注入监听脚本 _webController.runJavaScript(''' // 拦截XMLHttpRequest的open和send方法 const originalXHRopen = XMLHttpRequest.prototype.open; XMLHttpRequest.prototype.open = function(method, url) { this.addEventListener('load', () => { if (method.toUpperCase() === 'POST') { const payload = this.__requestData || '无请求体'; window.RequestCaptureChannel.postMessage(JSON.stringify({ method, url, payload, response: this.responseText, type: 'xhr' })); } }); return originalXHRopen.apply(this, arguments); }; const originalXHRsend = XMLHttpRequest.prototype.send; XMLHttpRequest.prototype.send = function(data) { this.__requestData = data; return originalXHRsend.apply(this, arguments); }; // 拦截Fetch API const originalFetch = window.fetch; window.fetch = function(input, init) { const method = (init?.method || 'GET').toUpperCase(); const requestUrl = typeof input === 'string' ? input : input.url; if (method === 'POST') { const payload = init?.body || '无请求体'; // 请求发送前捕获数据 window.RequestCaptureChannel.postMessage(JSON.stringify({ method, url: requestUrl, payload, timing: 'beforeSend', type: 'fetch' })); } // 请求完成后捕获响应 return originalFetch.apply(this, arguments).then(response => { response.clone().text().then(body => { window.RequestCaptureChannel.postMessage(JSON.stringify({ method: (init?.method || 'GET').toUpperCase(), url: requestUrl, response: body, timing: 'afterSend', type: 'fetch' })); }); return response; }); }; '''); }, ), ); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('WebView请求监听')), body: WebViewWidget(controller: _webController), ); } }
Ionic 实现方式
Ionic(无论用Capacitor还是Cordova)同样可以通过注入JS脚本拦截请求,再通过原生桥接将数据传回应用。下面以Capacitor为例:
代码示例
import { Component, OnInit } from '@angular/core'; import { App, WebView } from '@capacitor/app'; @Component({ selector: 'app-webview-capture', template: ` <ion-header> <ion-toolbar> <ion-title>WebView请求捕获</ion-title> </ion-toolbar> </ion-header> <ion-content> <capacitor-web-view [src]="targetUrl"></capacitor-web-view> </ion-content> `, }) export class WebviewCapturePage implements OnInit { targetUrl = 'https://your-target-page.com'; async ngOnInit() { const webView = await WebView.getWebView(); // 页面加载完成后注入监听脚本 webView.addListener('ionPageDidLoad', async () => { await webView.evaluateJavaScript(` // 拦截XMLHttpRequest const originalXHRopen = XMLHttpRequest.prototype.open; XMLHttpRequest.prototype.open = function(method, url) { this.addEventListener('load', () => { if (method.toUpperCase() === 'POST') { const payload = this.__requestData || '无请求体'; // 通过Capacitor发送事件到原生 window.Capacitor.App.fireNativeEvent('webviewRequestCaptured', { method, url, payload, response: this.responseText, type: 'xhr' }); } }); return originalXHRopen.apply(this, arguments); }; const originalXHRsend = XMLHttpRequest.prototype.send; XMLHttpRequest.prototype.send = function(data) { this.__requestData = data; return originalXHRsend.apply(this, arguments); }; // 拦截Fetch API const originalFetch = window.fetch; window.fetch = function(input, init) { const method = (init?.method || 'GET').toUpperCase(); const requestUrl = typeof input === 'string' ? input : input.url; if (method === 'POST') { const payload = init?.body || '无请求体'; window.Capacitor.App.fireNativeEvent('webviewRequestCaptured', { method, url: requestUrl, payload, timing: 'beforeSend', type: 'fetch' }); } return originalFetch.apply(this, arguments).then(response => { response.clone().text().then(body => { window.Capacitor.App.fireNativeEvent('webviewRequestCaptured', { method: (init?.method || 'GET').toUpperCase(), url: requestUrl, response: body, timing: 'afterSend', type: 'fetch' }); }); return response; }); }; `); }); // 监听原生事件,接收WebView传来的请求数据 App.addListener('webviewRequestCaptured', (data: any) => { console.log('捕获到WebView请求:', data); // 对接你的注册逻辑,比如提取payload中的用户信息 }); } }
关键安全提醒
你提到的安全风险确实需要重视:
- 注入的监听脚本可能被页面内的恶意JS篡改,导致数据泄露或请求伪造,建议只监听可信域名的页面。
- 捕获的POST载荷可能包含敏感信息(如密码、验证码),务必在应用端加密存储和传输,避免本地泄露。
- 不要将捕获的数据用于非预期用途,严格遵循隐私合规要求。
内容的提问来源于stack exchange,提问作者bbrooks96
相关产品推荐
相关产品推荐

