起因:

有些时候自家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. thymeleaf 货币格式化 数字格式化问题

    格式化数字对象 ${'¥'+#numbers.formatDecimal(pro.price,0,'COMMA',2,'POINT')} ${'¥'+#numbers.formatDecimal(pr ...

  2. maven工程,java代码加载resources下面资源文件的路径

    1 通过类加载器加载器, 1. URL resource = TestMain.class.getResource("/18500228040.txt");File file = ...

  3. AXIS2整合spring需要的jar,以及大部分缺少jar所报的异常

    axis2 webservice 服务端jar包: -->axis2-kernel-1.6.1.jar                              -->axis2-spri ...

  4. MySQL松散索引扫描与紧凑索引扫描

    什么是松散索引? 答:实际上就是当MySQL 完全利用索引扫描来实现GROUP BY 的时候,并不需要扫描所有满足条件的索引键即可完成操作得出结果. 要利用到松散索引扫描实现GROUP BY,需要至少 ...

  5. PAT1017:Queueing at Bank

    1017. Queueing at Bank (25) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue Supp ...

  6. SpringMVC中参数绑定

    SpringMVC中请求参数的接收主要有两种方式, 一种是基于HttpServletRequest对象获取, 另外一种是通过Controller中的形参获取 一  通过HttpServletReque ...

  7. 【手记】解决EXCEL跑SQL遇“查询无法运行或数据库表无法打开...”

    报错: 解决:在语句开头指定SET NOCOUNT ON 就是这么神cao奇dan. -END-

  8. 为何没有asia/beijing时区?

    Asia/Beijing 这个时区是消失了么? 大约1小时 ago @tinyfool 对啊,我就奇怪为什么北京时间就要用上海和成都... 大约1小时 ago @tinyfool @CatChen我所 ...

  9. CMD命令锦集

    虽然随着计算机产业的发展,Windows 操作系统的应用越来越广泛,DOS 面临着被淘汰的命运,但是因为它运行安全.稳定,有的用户还在使用,所以一般Windows 的各种版本都与其兼容,用户可以在Wi ...

  10. 你不知道的JavaScript--Item12 undefined 与 null

    当讨论JavaScript中的原始数据类型时,大多数人都知道从String.Number到Boolean的基本知识.这些原始类型相当简单,行为符合常识.但是,本文将更多关注独特的原始数据类型Null和 ...