我正在开发一个Android应用程序,用于过滤请求(使用白名单)并使用自定义SSLSocketFactory
。为此,我开发了一个自定义WebViewClient
,我已经覆盖了shouldInterceptRequest
方法。我可以使用GET请求过滤和使用SocketFactory
,但我无法拦截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);
}
}
答案 0 :(得分:4)
几天前我遇到了同样的问题。
所以我建立了一个解决它的库:
https://github.com/KonstantinSchubert/request_data_webviewclient
它是一个带有自定义WebResourceRequest的WebViewClient,它包含XMLHttpRequest请求的POST / PUT / ...有效负载。
它仅适用于这些 - 不适用于表单和其他类型的请求源。
基本上,通过在拦截XMLHttpRequest调用的HTML中注入脚本,hack起作用。它记录post / put / ...内容并将其发送到android.webkit.JavascriptInterface
。在那里,请求被隐藏,直到Android调用shouldInterceptRequest
方法...
答案 1 :(得分:1)
使用GET代替POST。
已知问题: http://code.google.com/p/android/issues/detail?id=9122
此处也有人回答: Android - how to intercept a form POST in android WebViewClient on API level 4
答案 2 :(得分:0)
我在上面的帖子http://code.google.com/p/android/issues/detail?id=9122
上有我的一个答案请参阅comment#31
我看到的解决方案的一些注意事项是:
除此之外,我发现this github repo似乎是以另一种黑客方式解决这个问题。我查看了代码,但没有时间来实现和测试它。但值得一试。
答案 3 :(得分:0)
您可以在提交前获得输入值
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());
}
});
答案 4 :(得分:0)
我发现最简单的方法是将 JQuery Ajax Event Handlers 与 Javascript 接口一起使用。
您必须设置 Javascript 接口,但是一旦您设置了它,就可以匹配您感兴趣的处理程序的签名。
要获取payload,只要找到payload变量名把它放在接口中即可。
这是 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
}
}
在 onPageStarted 覆盖中为 WebViewClient 注册
webView.addJavascriptInterface(yourJSInterface,"myJSInterface")
最后在 OnPageFinished 覆盖中将 JS 注入到 WebView 中
webView.evaluateJavascript("javascript:" + getString(R.string.js_from_above),null)
我在 onPageStarted 中注册了接口,否则 onPageFinished 中的 javascript 文件将无法识别您的接口。
答案 5 :(得分:0)
有一个更简单的解决方案:在ajax调用中通过GET发送参数并在shouldInterceptRequest中将它们转换为POST