Home » Android » android – Intercept POST requests in a WebView

android – Intercept POST requests in a WebView

Posted by: admin April 23, 2020 Leave a comment

Questions:

I’m developping an Android application filtering the requests (with a white list) and using a custom SSLSocketFactory. For this, I’ve developed a custom WebViewClient and I have overridden the shouldInterceptRequest method. I can filter and use my SocketFactory with the GET requests but I can’t intercept the POST requests.

So, is there a way to intercept the POST requests in a WebView ?

Here is the code of the shouldInterceptRequest method :

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);
    }
}
How to&Answers:

I was facing the same issue a few days ago.

So I built a library that solves it:

https://github.com/KonstantinSchubert/request_data_webviewclient

It is a WebViewClient with a custom WebResourceRequest that contains the POST/PUT/… payload of XMLHttpRequest requests.

It only works for these though – not for forms and other kind of request sources.

The hack works, basically, by injecting a script into the HTML that intercepts XMLHttpRequest calls. It records the post/put/… content and sends it to an android.webkit.JavascriptInterface. There, the request is stashed until the shouldInterceptRequest method is called by Android …

Answer:

you can get input value before submit

https://github.com/henrychuangtw/WebView-Javascript-Inject

Step 1 : create a class which called by javascript

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

Step 2 : register interface for javascript

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

Step 3 : inject javascript to page

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());
    }

});

Answer:

Use GET instead of POST.

Known issue:
http://code.google.com/p/android/issues/detail?id=9122

Was answered here as well:
Android – how to intercept a form POST in android WebViewClient on API level 4

Answer:

I have one of my answers on above thread http://code.google.com/p/android/issues/detail?id=9122

Please see comment#31

Some of the caveats of my solution I see are:

  1. Putting a dependency on xmlhttprequest prototype which has different implementation for different webkits.
  2. Security issue in sending data for post requests in URL. But I guess you can solve that through some encryption mechanism.
  3. URL length issue for some of the browsers if you big data to post

Apart from that, I found this github repo which seems to be solving this problem in another hacky way. I looked into the code but didn’t get time to implement and test it. But worth giving a try.