javascript - 为什么 XMLHttpRequest 在 Android 中打开并发送未使用 javascript 调用?
问题描述
我试图在使用 webView 打开 HTML 页面之前拦截 POST 请求。我按照以下教程进行操作:https://medium.com/@madmuc/intercept-all-network-traffic-in-webkit-on-android-9c56c9262c85 通过资产文件夹中的 .js 文件注入 javascript 文件:
XMLHttpRequest.prototype.origOpen = XMLHttpRequest.prototype.open;
XMLHttpRequest.prototype.open = function(method, url, async, user, password) {
// these will be the key to retrieve the payload
this.recordedMethod = method;
this.recordedUrl = url;
this.origOpen(method, url, async, user, password);
};
XMLHttpRequest.prototype.origSend = XMLHttpRequest.prototype.send;
XMLHttpRequest.prototype.send = function(body) {
// interceptor is a Kotlin interface added in WebView
if(body) recorder.recordPayload(this.recordedMethod, this.recordedUrl, body);
this.origSend(body);
};
但是,从不调用 open 和 send,我添加了日志进行测试,如果我将 recorder.recordPayload(...)
(这是 javascript 接口中的方法)移出这些函数,则recordPayload
调用,所以问题不在于接口或从文件。
网络视图类:
class TestWebView : WebView {
private var urlReturned = false
private var postbackUrl: String? = "https://www.xxxxx.com"
private var postbackHandled = false```
lateinit var recorder: PayloadRecorder
lateinit var payload: String
constructor(context: Context?) : super(context) {
initUI()
}
private fun initUI() {
if (!isInEditMode) {
settings.javaScriptEnabled = true
settings.builtInZoomControls = true
settings.displayZoomControls = false
settings.loadWithOverviewMode = true
settings.useWideViewPort = true
recorder = PayloadRecorder()
addJavascriptInterface(recorder, "recorder")
evaluateJavascript(
context.assets.open("override.js").reader().readText(), null
)
}
val client: WebViewClient = object : WebViewClient() {
override fun shouldInterceptRequest(
view: WebView,
request: WebResourceRequest
): WebResourceResponse? {
val payload = recorder.getPayload(request.method, request.url.toString())
// handle the request with the given payload and return the response
return super.shouldInterceptRequest(view, request)
}
override fun onPageStarted(
view: WebView,
url: String,
favicon: Bitmap?
) {
Log.i("testURL", url)
evaluateJavascript(
context.assets.open("override.js").reader().readText(),
object : ValueCallback<String> {
override fun onReceiveValue(value: String?) {
Log.i("onReceiveValue", value)
}
}
)
}
}
setWebChromeClient(object : WebChromeClient() {
override fun onConsoleMessage(consoleMessage: ConsoleMessage): Boolean {
Log.d("WebView", consoleMessage.message())
return true
}
})
}
constructor(context: Context?, attrs: AttributeSet?) : super(
context,
attrs
) {
initUI()
}
constructor(
context: Context?,
attrs: AttributeSet?,
defStyle: Int
) : super(context, attrs, defStyle) {
initUI()
}
constructor(
context: Context?,
attrs: AttributeSet?,
defStyle: Int,
privateBrowsing: Boolean
) : super(context, attrs, defStyle) {
initUI()
}
class PayloadRecorder {
private val payloadMap: MutableMap<String, String> =
mutableMapOf()
@JavascriptInterface
fun recordPayload(
method: String,
url: String,
payload: String
) {
payloadMap["$method-$url"] = payload
Log.i("payloadRecorder", "recordPayLoad")
}
fun getPayload(
method: String,
url: String
): String? =
payloadMap["$method-$url"]
}
/**
* The function that is called and starts the html progress
*/
@JvmOverloads
fun process(
acsUrl: String?,
md: String?,
paReq: String?,
postbackUrl: String? = null
) {
urlReturned = false
postbackHandled = false
if (!TextUtils.isEmpty(postbackUrl)) {
this.postbackUrl = postbackUrl
}
val postParams: String
payload = paReq?: ""
postParams = //my code
postUrl(acsUrl, postParams.toByteArray())
}
}
recordPayload
永远不会被调用,因此 in shouldInterceptRequest
payload
总是返回 null。
解决方案
推荐阅读
- java - 如何使用广播接收器在android和另一个进程之间进行通信
- c# - 如何解决 BotChat.App 未捕获的 ReferenceError?
- android - RecyclerView 和 Activity 之间的 Material Design 动画过渡
- angular - 如何在选择上简化 *ngFor
- highcharts - 带有表格和子任务的 Higcharts 甘特图
- c# - 如何向 Discord Webhooks C# 发送 POST 请求
- python - Pycopula 库输入
- python - 通过 discord py 发送 webhook 消息以克隆用户消息
- apache-nifi - NiFi:尽管在 nifi.properties 中进行了设置,但 content_repository 已满
- javascript - 无法执行 div 元素的拖放