起因:

有些时候自家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地址:webview_post_data

大家如果有什么疑问或者建议可以通过评论或者邮件的方式联系我,欢迎大家的评论~

Android拦截并获取WebView内部POST请求参数的更多相关文章

  1. springboot springmvc拦截器 拦截POST、PUT、DELETE请求参数和响应数据,并记录操作日志

    1.操作日志实体类 @Document(collection = "operation_log") @Getter @Setter @ToString public class O ...

  2. java从request中获取GET和POST请求参数

    URL和参数列表 一 获取请求方式 request.getMethod(); get和post都可用, 二 获取请求类型 request.getContentType(); get和post都可用,示 ...

  3. requset获取post提交的请求参数

    1.请求体的内容通常是通过post来提交的,格式是 username=zhansan&password=123&hobby=football||&hobby=basketbal ...

  4. java 获取request中的请求参数

    1.get 和 post请求方式 (1)request.getParameterNames(); 获取所有参数key后.遍历request.getParameter(key)获取value (2)re ...

  5. SpringBoot 拦截器获取http请求参数

    SpringBoot 拦截器获取http请求参数-- 所有骚操作基础 目录 SpringBoot 拦截器获取http请求参数-- 所有骚操作基础 获取http请求参数是一种刚需 定义拦截器获取请求 为 ...

  6. jmeter脚本中请求参数获取的几种方式

     a.从数据库获取: 譬如接口请求参数中id的值,我需要从数据库获取,如下设置: 先设置jdbc connection configuration,然后设置JDBC b.从CSV获取: 获取CSV文件 ...

  7. struts2视频学习笔记 11-12(动态方法调用,接收请求参数)

    课时11 动态方法调用 如果Action中存在多个方法时,可以使用!+方法名调用指定方法.(不推荐使用) public String execute(){ setMsg("execute&q ...

  8. Android之网络----使用HttpClient发送HTTP请求(通过get方法获取数据)

    [正文] 一.HTTP协议初探: HTTP(Hypertext Transfer Protocol)中文 "超文本传输协议",是一种为分布式,合作式,多媒体信息系统服务,面向应用层 ...

  9. [Android] 获取WebView的页面标题(Title)-----WebChromeClient.onReceivedTitle()方法的重写

    应用开发中需要获取WebView当前页面的标题,可能通过对WebChromeClient.onReceivedTitle()方法的重写来实现 效果图如下: 代码如下: public class Mai ...

随机推荐

  1. python_方法说明

    方法用来描述对象所具有的行为,例如,列表对象的追加元素.插入元素.删除原宿.排序,字符串对象的分隔.连接.排版.替换.烤箱的温度设置.烘烤,等等 在类中定义的方法可以粗略分为四大类:公有方法.私有方法 ...

  2. C# DataGridView绑定List对象时,利用BindingList来实现增删查改

    当DataGridView的DataSource是DataTable的时候,DataTable的数据改变时,DataGridView的数据会随之改变,无需重新绑定到DataGridView.  当Da ...

  3. 使用 Swoole 来加速你的 Laravel 应用

    Swoole 是为 PHP 开发的生产级异步编程框架. 他是一个纯 C 开发的扩展, 他允许 PHP 开发者在 PHP 中写 高性能,可扩展的并发 TCP, UDP, Unix socket, HTT ...

  4. Java中 float、double使用注意问题

    在java中运行一下代码 System.out.println(2.00-1.10);输出的结果是:0.8999999999999999很奇怪,并不是我们想要的值0.9 再运行如下代码:System. ...

  5. Oracle-12:伪列rowid和rownum

    ------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- 伪列:不真实存储在真表中,但是我们可以查询到不能对伪列进行增删改操作! 分页可以用rownum来分!!!!!! ...

  6. mysql事务隔离级别详解和实战

    A事务做了操作 没有提交 对B事务来说 就等于没做 获取的都是之前的数据 但是 在A事务中查询的话 查到的都是操作之后的数据 没有提交的数据只有自己看得到,并没有update到数据库. 查看InnoD ...

  7. 多进程Multiprocessing模块

    多进程 Multiprocessing 模块 先看看下面的几个方法: star() 方法启动进程, join() 方法实现进程间的同步,等待所有进程退出. close() 用来阻止多余的进程涌入进程池 ...

  8. fixed 和 absolute 定位的区别

    fixed:固定定位           absolute:绝对定位 在没有滚动条的情况下两者其实没有差异.但是在有滚动条后,fixed始终会在定好的位置不动,而absolute会随参照对象元素的宽高 ...

  9. Class path & Path

    Class path: 配置类文件 (配置完之后,在任何盘符下都可以访问该配置路径下的文件); Path: 配置可执行文件; Class path 配置时路径后面加分号与不加分号的区别 (当前路径与配 ...

  10. C++中虚拟继承

    多重继承 在多重继承中,基类的构造函数的调用次序即不受派生类构造函数初始化列表中出现的基类构造函数的影响,也不受基类在构造函数初始化列表中的出现次序的影响,它按照基类在类派生列表中的出现次序依次调用相 ...