拦截WebView中的POST请求

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

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

这是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); } } 

几天前我也遇到了同样的问题。

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

https://github.com/KonstantinSchubert/request_data_webviewclient

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

它只适用于这些 – 不适用于表单和其他types的请求源。

该hack基本上是通过将一个脚本注入到拦截XMLHttpRequest调用的HTML中来实现的。 它记录post / put / …内容并将其发送到android.webkit.JavascriptInterface 。 在那里,请求被存储,直到Android调用了shouldInterceptRequest方法…

使用GET而不是POST。

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

这里也回答了: Android – 如何在API级别4上拦截Android WebViewClient中的表单POST

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

请参阅#31评论

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

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

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

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

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

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

第2步:注册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()); } });