Android拦截并获取WebView内部POST请求参数

  • 起因
  • 实现过程
    • ~~方案一~~
    • 方案二
  • 反思
  • GitHub地址:[webview_post_data](https://github.com/lxr17/webview_post_data)

起因

有些时候自家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>

客户端拦截请求:

@Overridepublic 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"。

反思

  • 开发过程中遇到了页面一直显示不了的问题,实际上就是因为获取到的mimetext/html; charset=utf-8,得改成text/html
  • 通过此方法也可篡改responserequest,但不要滥用;
  • 所以说,Android确实不安全!

GitHub地址:webview_post_data

更多相关文章

  1. 关于更新Android(安卓)sdk之后出现This Android(安卓)SDK requir
  2. 服务器基于PHP CodeIgniter,Android基于Volley实现多文件/图片上
  3. 如何使用jdb调试android的java程序
  4. Android(安卓)进阶——持久化存储序列化方案Serializable和IPC及
  5. 深入解读Android的内部进程通信接口AIDL
  6. Android(安卓)Server Push - MQTT
  7. mac下安装android studio 遇到问题及解决方案
  8. 关于Android(安卓)Service真正的完全详解,你需要知道的一切
  9. sqlite3加密方案sqlcipher,及sqlcipher使用指南

随机推荐

  1. 如何快速学习一门新技术
  2. 解决 Android(安卓)Studio 乱码问题
  3. Android(安卓)Studio SVN配置忽略文件 1.
  4. Android学习笔记(一):基本概念
  5. android五子棋游戏源码
  6. Android应用权限及意义
  7. Android(安卓)Settings添加选项
  8. android studio 更新 Gradle错误解决方法
  9. 有关布局问题:TextView、EditText……(二)
  10. Netbeans 装Android