Android拦截并获取WebView内部POST请求参数的实现方法
程序员文章站
2023-11-09 12:45:28
起因:
有些时候自家app中嵌入的h5页面并不是自家的。但是很多时候又想在h5不知情的情况下获取h5内部请求的参数,这应该怎么做到呢?
带着这个疑问,就有了这篇博客。...
起因:
有些时候自家app中嵌入的h5页面并不是自家的。但是很多时候又想在h5不知情的情况下获取h5内部请求的参数,这应该怎么做到呢?
带着这个疑问,就有了这篇博客。
实现过程:
方案一:
最开始想到的方案是直接拦截h5中所有的请求:
webview.setwebviewclient(new webviewclient() { @override public webresourceresponse shouldinterceptrequest(webview view, webresourcerequest request) { try { url url = new url(request.geturl()); } catch (malformedurlexception e) { e.printstacktrace(); } log.e("internetactivity", request + ""); return super.shouldinterceptrequest(view, request); } });
但是通过此方法只能获取get请求的参数(因为参数直接拼在了url链接中),对于post请求的参数无可奈何。
方案二:
后来参考了request_data_webviewclient,有了新的实现方式,具体原理为:给h5注入一段js代码,目的是在每次ajax请求都会调用android原生的方法,将请求参数传给客户端。
具体流程如下:
其中,
js注入代码:
<script language="javascript"> function generaterandom() { return math.floor((1 + math.random()) * 0x10000) .tostring(16) .substring(1); } // this only works if `open` and `send` are called in a synchronous way // that is, after calling `open`, there must be no other call to `open` or // `send` from another place of the code until the matching `send` is called. requestid = null; xmlhttprequest.prototype.reallyopen = xmlhttprequest.prototype.open; xmlhttprequest.prototype.open = function(method, url, async, user, password) { requestid = generaterandom() var signed_url = url + "ajaxintercept" + requestid; this.reallyopen(method, signed_url , async, user, password); }; xmlhttprequest.prototype.reallysend = xmlhttprequest.prototype.send; xmlhttprequest.prototype.send = function(body) { interception.customajax(requestid, body); this.reallysend(body); }; </script>
客户端拦截请求:
@override public final webresourceresponse shouldinterceptrequest(final webview view, webresourcerequest request) { string requestbody = null; uri uri = request.geturl(); // 判断是否为ajax请求(只要链接中包含ajaxintercept即是) if (isajaxrequest(request)) { // 获取post请求参数 requestbody = getrequestbody(request); // 获取原链接 uri = getoriginalrequesturi(request, marker); } // 重新构造请求,并获取response webresourceresponse webresourceresponse = shouldinterceptrequest(view, new writehandlingwebresourcerequest(request, requestbody, uri)); if (webresourceresponse == null) { return webresourceresponse; } else { return injectintercept(webresourceresponse, view.getcontext()); } }
客户端注入js代码:
private webresourceresponse injectintercept(webresourceresponse response, context context) { string encoding = response.getencoding(); string mime = response.getmimetype(); // webresourceresponse的mime必须为"text/html",不能是"text/html; charset=utf-8" if (mime.contains("text/html")) { mime = "text/html"; } inputstream responsedata = response.getdata(); inputstream injectedresponsedata = injectintercepttostream( context, responsedata, mime, encoding ); return new webresourceresponse(mime, encoding, injectedresponsedata); }
注:根据谷歌官方文档,mime必须为"text/html"。
反思:
•开发过程中遇到了页面一直显示不了的问题,实际上就是因为获取到的mime是"text/html; charset=utf-8",得改成"text/html";
•通过此方法也可篡改response与request,但不要滥用;
•所以说,android确实不安全!
github地址:
总结
以上所述是小编给大家介绍的android拦截并获取webview内部post请求参数的实现方法,希望对大家有所帮助
上一篇: Android开发菜单布局之表格布局示例