Android 在WebView中拦截POST请求
我正在开发一个Android应用程序来过滤请求(带有一个白名单),并使用一个定制的Android 在WebView中拦截POST请求,android,post,webview,request,Android,Post,Webview,Request,我正在开发一个Android应用程序来过滤请求(带有一个白名单),并使用一个定制的SSLSocketFactory。为此,我开发了一个定制的WebViewClient,并重写了shouldInterceptRequest方法。我可以对GET请求过滤并使用我的SocketFactory,但我无法截获POST请求 那么,有没有办法在WebView中拦截POST请求呢 以下是shoulInterceptRequest方法的代码: public final WebResourceResponse sho
SSLSocketFactory
。为此,我开发了一个定制的WebViewClient
,并重写了shouldInterceptRequest
方法。我可以对GET请求过滤并使用我的SocketFactory
,但我无法截获POST请求
那么,有没有办法在WebView
中拦截POST请求呢
以下是shoulInterceptRequest方法的代码:
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);
}
}
使用GET而不是POST 已知问题: 这里也有人回答:
我在上面的帖子中有一个答案 请看 我看到的解决方案的一些警告是:
除此之外,我发现它似乎以另一种骇人的方式解决了这个问题。我研究了代码,但没有时间实现和测试它。但是值得一试。您可以在提交之前获得输入值
步骤1:创建一个由javascript调用的类
class MyJavaScriptInterface
{
@JavascriptInterface
public void processHTML(String html)
{
//called by javascript
}
}
webview1.getSettings().setJavaScriptEnabled(true);
webview1.addJavascriptInterface(new MyJavaScriptInterface(), "MYOBJECT");
步骤2:注册javascript接口
class MyJavaScriptInterface
{
@JavascriptInterface
public void processHTML(String html)
{
//called by 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());
}
});
webview1.setWebViewClient(新的WebViewClient(){
@凌驾
公共void onPageFinished(WebView视图,字符串url){
super.onPageFinished(视图、url);
StringBuilder sb=新的StringBuilder();
append(“document.getElementsByTagName('form')[0].onsubmit=function(){”);
sb.追加(“var objPWD,objAccount;var str=”;”;
sb.append(“var inputs=document.getElementsByTagName('input');”;
sb.append(“for(vari=0;i
几天前我也面临同样的问题
所以我建立了一个库来解决这个问题:
它是一个WebViewClient,具有自定义WebResourceRequest,其中包含POST/PUT/。。。XMLHttpRequest请求的负载
但它只适用于这些应用程序,而不适用于表单和其他类型的请求源
黑客的工作原理基本上是将一个脚本注入到拦截XMLHttpRequest调用的HTML中。它记录post/put/。。。内容并将其发送到一个
android.webkit.JavascriptInterface
。在那里,请求被隐藏,直到Android调用shouldInterceptRequest
方法…我发现最简单的方法就是使用Javascript接口
您必须设置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);
});
这是科特林班
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 override for WebViewClient中的注册已启动
webView.addJavascriptInterface(yourJSInterface,"myJSInterface")
最后,将JS注入到OnPageFinished覆盖中的WebView中
webView.evaluateJavascript("javascript:" + getString(R.string.js_from_above),null)
我在onPageStarted中注册了该接口,因为否则,onPageFinished中的javascript文件将无法识别您的接口。有一个更简单的解决方案:通过ajax调用中的GET发送参数,并将其转换为shouldInterceptRequest中的POST您是否收到错误,或者根本不起作用?你应该发布一些相关的代码,比如你被重写的
shouldInterceptRequest
方法。不,我没有错误。我在shoulInterceptRequest方法的开始处记录url,只看到GET请求。其他的似乎是在WebView低层管理的。是的,我在android bugtracker中发现了这个问题。但在我的情况下,我无法将POST更改为GET请求,因为我不知道将连接到哪个服务器。例如,我无法连接到GMail,因为在身份验证过程中有一个POST请求。看看这个库:我在遇到类似问题时写的。这个问题非常聪明。谢谢转换为与Xamarin.Android一起工作,并在面临此问题时节省了时间。