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