web-dev-qa-db-fra.com

Intercepter POST requêtes dans une WebView

Je développe une application Android filtrant les demandes (avec une liste blanche) et utilisant une variable SSLSocketFactory personnalisée. Pour cela, j'ai développé une WebViewClient personnalisée et j'ai remplacé la méthode shouldInterceptRequest. Je peux filtrer et utiliser ma SocketFactory avec les demandes GET mais je ne peux pas intercepter les demandes POST.

Alors, y a-t-il un moyen d’intercepter les demandes POST dans une WebView?

Voici le code de la méthode 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);
    }
}
28
Fab_34

Je faisais face au même problème il y a quelques jours.

J'ai donc construit une bibliothèque qui le résout: 

https://github.com/KonstantinSchubert/request_data_webviewclient

Il s'agit d'un WebViewClient avec un WebResourceRequest personnalisé contenant la charge POST/PUT/... des demandes XMLHttpRequest.

Cela ne fonctionne cependant que pour ceux-ci - pas pour les formulaires et autres types de sources de demandes.

Le hack fonctionne, fondamentalement, en injectant un script dans le HTML qui intercepte les appels XMLHttpRequest. Il enregistre le contenu de l'article/put/... et l'envoie à un Android.webkit.JavascriptInterface. Là, la demande est stockée jusqu'à ce que la méthode shouldInterceptRequest soit appelée par Android ...

3
Konstantin Schubert
1
Raanan

vous pouvez obtenir une valeur d'entrée avant de soumettre
https://github.com/henrychuangtw/WebView-Javascript-Inject

Étape 1: créer une classe appelée par javascript

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


Étape 2: enregistrez une interface pour javascript

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


Étape 3: injecter du javascript à la 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());
    }

});
0
HenryChuang

J'ai une de mes réponses sur le fil ci-dessus http://code.google.com/p/Android/issues/detail?id=9122

S'il vous plaît voir commentaire # 31

Certaines des mises en garde de ma solution sont les suivantes:

  1. Créer une dépendance sur le prototype xmlhttprequest qui a une implémentation différente pour différents kits Web.
  2. Problème de sécurité lors de l'envoi de données pour les demandes de publication dans une URL. Mais je suppose que vous pouvez résoudre ce problème grâce à un mécanisme de cryptage.
  3. Problème de longueur d'URL pour certains navigateurs si vous souhaitez publier des données volumineuses

En dehors de cela, j'ai trouvé ce github repo qui semble résoudre ce problème d'une autre manière hacky. J'ai examiné le code mais je n'ai pas eu le temps de le mettre en œuvre et de le tester. Mais ça vaut le coup d'essayer.

0
chetan pawar