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
これは、XMLHttpRequest要求のPOST/PUT/...ペイロードを含むカスタムWebResourceRequestを持つWebViewClientです。
ただし、これらの場合にのみ機能します。フォームやその他の種類のリクエストソースには機能しません。
このハッキングは、基本的に、XMLHttpRequest呼び出しをインターセプトするスクリプトをHTMLに挿入することで機能します。 post/put/...コンテンツを記録し、Android.webkit.JavascriptInterface
。そこで、Android ...によってshouldInterceptRequest
メソッドが呼び出されるまで、リクエストは隠されます。
POSTの代わりにGETを使用します。
既知の問題: http://code.google.com/p/Android/issues/detail?id=9122
ここでも回答されました: Android-フォームをインターセプトする方法POST in Android APIレベル4のWebViewClient
送信する前に入力値を取得できます
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());
}
});
上記のスレッドについて回答があります http://code.google.com/p/Android/issues/detail?id=9122
comment#31 をご覧ください
私が見る私のソリューションのいくつかの警告は次のとおりです。
それとは別に、私は this github repo を見つけました。これは、この問題を別のハッキング方法で解決しているようです。私はコードを調べましたが、それを実装してテストする時間はありませんでした。しかし、試してみる価値はあります。