zoukankan      html  css  js  c++  java
  • Android拦截并获取WebView内部POST请求参数

    起因:

    有些时候自家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确实不安全!

    GitHub地址:webview_post_data

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

  • 相关阅读:
    manjaro 安装mysql
    Ubuntu安装Redis
    Ubuntu安装docker
    VirtualBox 安装 Ubuntu虚拟机 显卡驱动
    ubuntu 卸载软件
    Linux下环境变量设置的三种方法:
    error: open of glibc-devel-2.12-1.132.el6.i686.rpm failed: 没有那个文件或目录
    ip地址0.0.0.0与127.0.0.1的区别(转载)
    cmake的安装和卸载
    qmake 提示 Failure to open file:****
  • 原文地址:https://www.cnblogs.com/lanxingren/p/10697106.html
Copyright © 2011-2022 走看看