34

我正在开发一个过滤请求(带有白名单)并使用自定义的 Android 应用程序SSLSocketFactory。为此,我开发了一个自定义WebViewClient并覆盖了该shouldInterceptRequest方法。我可以过滤并使用我SocketFactory的 GET 请求,但我无法拦截 POST 请求。

那么,有没有办法拦截 POST 请求WebView

这是 shouldInterceptRequest 方法的代码:

public final WebResourceResponse shouldInterceptRequest(WebView view, String urlStr) {
    URI uri = URI.create(urlStr);
    String scheme = uri.getScheme();
    // If scheme not http(s), let the default webview manage it
    if(!"http".equals(scheme) && !"https".equals(scheme)) {
        return null;
    }
    URL url = uri.toURL();

    if(doCancelRequest(url)) {
        // Empty response
        Log.d(TAG, "URL filtered: " + url);
        return new WebResourceResponse("text/plain", "UTF-8", new EmptyInputStream());

    } else {
        Log.d(TAG, "URL: " + url);

        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestProperty("User-Agent", mSettings.getUserAgentString());

        // Configure connections
        configureConnection(conn);

        String mimeType = conn.getContentType();
        String encoding = conn.getContentEncoding();

        if(mimeType != null && mimeType.contains(CONTENT_TYPE_SPLIT)) {
            String[] split = mimeType.split(CONTENT_TYPE_SPLIT);
            mimeType = split[0];

            Matcher matcher = CONTENT_TYPE_PATTERN.matcher(split[1]);
            if(matcher.find()) {
                encoding = matcher.group(1);
            }
        }

        InputStream is = conn.getInputStream();
        return new WebResourceResponse(mimeType, encoding, is);
    }
}
4

6 回答 6

7

几天前我也面临同样的问题。

所以我建立了一个解决它的库:

https://github.com/KonstantinSchubert/request_data_webviewclient

它是一个带有自定义 WebResourceRequest 的 WebViewClient,其中包含 XMLHttpRequest 请求的 POST/PUT/... 负载。

它只适用于这些——不适用于表单和其他类型的请求源。

hack 基本上是通过将脚本注入到拦截 XMLHttpRequest 调用的 HTML 中来工作的。它记录 post/put/... 内容并将其发送到android.webkit.JavascriptInterface. 在那里,请求被隐藏起来,直到shouldInterceptRequestAndroid 调用该方法......

于 2017-08-12T23:58:07.170 回答
0

使用 GET 而不是 POST。

已知问题: http ://code.google.com/p/android/issues/detail?id=9122

在这里也得到了回答: Android - 如何在 API 级别 4 的 android WebViewClient 中拦截表单 POST

于 2012-12-19T20:56:17.890 回答
0

有一个更简单的解决方案:在 ajax 调用中通过 GET 发送参数,并在 shouldInterceptRequest 中将它们转换为 POST

于 2021-04-30T22:07:08.713 回答
0

我在上面的线程 http://code.google.com/p/android/issues/detail?id=9122上有我的答案之一

请参阅评论#31

我看到的解决方案的一些注意事项是:

  1. 依赖于 xmlhttprequest 原型,它对不同的 webkits 有不同的实现。
  2. 在 URL 中为 post 请求发送数据时的安全问题。但我想你可以通过一些加密机制来解决这个问题。
  3. 如果您发布大数据,某些浏览器的 URL 长度问题

除此之外,我发现这个 github repo似乎以另一种 hacky 方式解决了这个问题。我查看了代码,但没有时间实现和测试它。但值得一试。

于 2015-07-15T05:53:39.820 回答
0

我发现最简单的方法是使用带有 Javascript 接口的JQuery Ajax 事件处理程序。

您必须设置 Javascript 接口,但是一旦您设置它与您感兴趣的处理程序的签名相匹配。

要获取有效负载,只需找到有效负载变量名称并将其放在界面中即可。

这是Javascript:

 $( document ).ajaxSend(function( event, request, settings ) {
      var eventJSON= JSON.stringify(event);
      var requestJSON = JSON.stringify(request);
      var settingsJSON = JSON.stringify(settings);
      var payloadJSON = JSON.stringify(payload);

      myJSInterface.passData(eventJSON,requestJSON,settingsJSON,payloadJSON);       
 });

这是 Kotlin 类

 class yourJSInterface() {
      lateinit var event: String
      lateinit var request: String
      lateinit var settings: String
      lateinit var payload: String
 
      @JavascriptInterface
      fun passData(eventJSON:String, responseJSON:String, settingsJSON:String,payloadJSON:String){
           event = eventJSON
           response= responseJSON
           settings= settingsJSON
           payload= payloadJSON
      }
 }

WebViewClient 的 onPageStarted 覆盖中的注册

 webView.addJavascriptInterface(yourJSInterface,"myJSInterface")

最后在 OnPageFinished 覆盖中将 JS 注入 WebView

 webView.evaluateJavascript("javascript:" + getString(R.string.js_from_above),null)

我在 onPageStarted 中注册了界面,否则 onPageFinished 中的 javascript 文件将无法识别您的界面。

于 2021-02-15T11:29:49.853 回答
-1

您可以在提交之前获取输入值
https://github.com/henrychuangtw/WebView-Javascript-Inject

第 1 步:创建一个由 javascript 调用的类

class MyJavaScriptInterface
{
    @JavascriptInterface
    public void processHTML(String html)
    {
        //called by javascript
    }
}


第二步:注册javascript接口

webview1.getSettings().setJavaScriptEnabled(true);
webview1.addJavascriptInterface(new MyJavaScriptInterface(), "MYOBJECT");


第 3 步:将 javascript 注入页面

webview1.setWebViewClient(new WebViewClient() {
    @Override
    public void onPageFinished(WebView view, String url) {
        super.onPageFinished(view, url);

        StringBuilder sb = new StringBuilder();
        sb.append("document.getElementsByTagName('form')[0].onsubmit = function () {");
        sb.append("var objPWD, objAccount;var str = '';");
        sb.append("var inputs = document.getElementsByTagName('input');");
        sb.append("for (var i = 0; i < inputs.length; i++) {");
        sb.append("if (inputs[i].type.toLowerCase() === 'password') {objPWD = inputs[i];}");
        sb.append("else if (inputs[i].name.toLowerCase() === 'email') {objAccount = inputs[i];}");
        sb.append("}");
        sb.append("if (objAccount != null) {str += objAccount.value;}");
        sb.append("if (objPWD != null) { str += ' , ' + objPWD.value;}");
        sb.append("window.MYOBJECT.processHTML(str);");
        sb.append("return true;");
        sb.append("};");

        view.loadUrl("javascript:" + sb.toString());
    }

});
于 2015-08-12T02:27:02.287 回答