如何在Android WebView中拦截HTTP Form Data获取认证令牌
Android WebView 提取Form Data认证令牌实现方案
Android 原生WebView 没有提供和iOS NavigationAction.httpBody 对等的直接获取POST请求Body的系统API,可通过以下两种稳定方案实现需求,核心逻辑和iOS端一致:先匹配目标回调URL,再提取对应POST请求的Form Data解析令牌。
方案1:注入JavaScript监听表单提交(兼容性最好,实现成本最低)
适合仅需要监听登录表单提交获取令牌的场景,适配全Android版本。
实现步骤:
- 开启WebView的JS权限,配置JS交互接口
// 开启JS支持 webView.settings.javaScriptEnabled = true // 注入原生交互接口,AndroidInterface为JS中调用的对象名 webView.addJavascriptInterface(AuthJsInterface(), "AndroidInterface")
- 自定义JS交互接口,接收JS传回的表单数据
class AuthJsInterface { @JavascriptInterface fun receiveFormData(formDataStr: String) { // formDataStr为序列化后的表单键值对,格式为key1=value1&key2=value2 formDataStr.split("&").forEach { keyValue -> val (key, value) = keyValue.split("=") // 替换为你的认证令牌对应的参数名 if (key == "auth_token") { val authToken = value.decode() // 拿到令牌后执行后续业务逻辑 } } } }
- 重写WebViewClient的
onPageFinished回调,页面加载完成后注入表单监听JS
override fun onPageFinished(view: WebView?, url: String?) { super.onPageFinished(view, url) // 仅在登录页加载完成后注入监听代码,替换为你的登录页URL特征 if (url?.contains("/login") == true) { view?.loadUrl(""" javascript:(function(){ // 监听页面所有表单的提交事件 const forms = document.getElementsByTagName('form'); for(let i=0; i<forms.length; i++){ forms[i].addEventListener('submit', function(e){ // 序列化表单数据 const formData = new FormData(this); let dataStr = ''; for(const [key, value] of formData.entries()){ if(dataStr) dataStr += '&'; dataStr += encodeURIComponent(key) + '=' + encodeURIComponent(value); } // 传回Android原生层 AndroidInterface.receiveFormData(dataStr); }); } })(); """.trimIndent()) } }
方案2:代理WebView网络请求(适合需要全量拦截请求的场景)
如果需要完全接管WebView的网络请求,可以重写shouldInterceptRequest回调,用OkHttp等网络库代理所有WebView请求,即可直接拿到POST请求的Body内容:
override fun shouldInterceptRequest( view: WebView?, request: WebResourceRequest ): WebResourceResponse? { // 替换为你的实际回调URL val targetCallbackUrl = "/identity/userAuthenticated" // 匹配目标POST请求 if (request.url.toString().contains(targetCallbackUrl) && request.method == "POST") { // 此处通过自定义的WebView代理网络栈,拿到对应请求的Body内容 // 解析Body中的Form Data即可提取认证令牌 } return super.shouldInterceptRequest(view, request) }
注意事项
- 使用JS注入方案时,需要在混淆规则中保留
AuthJsInterface类及其公开方法,避免被混淆后JS无法调用 - 如果表单提交格式为
multipart/form-data,需要单独编写对应格式的解析逻辑拆分内容 - Android 12及以上版本需注意WebView的隐私权限适配,避免JS交互被系统拦截
内容的提问来源于stack exchange,提问作者Artem
相关产品推荐
相关产品推荐

