起因:
有些时候自家app中嵌入的h5页面并不是自家的。但是很多时候又想在h5不知情的情况下获取h5内部请求的参数,这应该怎么做到呢?
带着这个疑问,就有了这篇博客。
实现过程:
方案一:
最开始想到的方案是直接拦截h5中所有的请求:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
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注入代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
<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> |
客户端拦截请求:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
@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代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
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地址:webview_post_data
总结
以上所述是小编给大家介绍的Android拦截并获取WebView内部POST请求参数的实现方法,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对服务器之家网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!
原文链接:https://www.cnblogs.com/lanxingren/archive/2019/04/12/10697106.html