Android与Webview交互
补充
- WebViewClient
- WebViewClient主要帮助WebView处理各种通知、请求事件的,比如:
- shouldOverrideUrlLoading
- onLoadResource
- onPageStart
- onPageFinish
- onReceiveError
- onReceivedHttpAuthRequest
- WebChromeClient
-WebChromeClient主要辅助WebView处理Javascript的对话框、网站图标、网站title、加载进度等比如
- onCloseWindow(关闭WebView)
- onCreateWindow()
- onJsAlert (WebView上alert无效,需要定制WebChromeClient处理弹出)
- onJsPrompt
- onJsConfirm
- onProgressChanged
- onReceivedIcon
- onReceivedTitle
-
Android与JS交互的几种方式
- webView.addJavascriptInterface(object,name)
- 通过向js中注入一个对象
- js通过window.name获取到对象,即可调用对象中的方法
-
漏洞
- 在Javascript代码中,利用Java反射机制,通过interfaceObject获取当前Runtime对象引用,并调用其exec方法执行nc命令连接服务器8088及8089端口。
- 漏洞说明引用
- WebViewClient.shouldOverrideUrlLoading()
- 通过自定义 webViewClient中的shouldOverrideUrlLoading方法
- 监听当前正在加载的url地址
- 通过解析url来做出相应操作
- WebChromeClient.onJsAlert()/onJsConfirm()/onJsPrompt() 方法分别回调拦截JS对话框alert()、confirm()、prompt()消息
- alert() 弹出个提示框 (确定)
- confirm() 弹出个确认框 (确定,取消)
- prompt() 弹出个输入框 让你输入东西
- 通过自定义webViewChromClient
- 主要是监听message 解析,做对应操作
- webView.addJavascriptInterface(object,name)
-
Android调用Js方法
- webView.loadUrl()
- mWebView.loadUrl("javascript:callJS()");
- mWebView.evaluateJavascript 使用如下
- 此方法只支持android 4.4以上
- webView.loadUrl()
mWebView.evaluateJavascript("javascript:callJS()", new ValueCallback<String>() {
@Override
public void onReceiveValue(String value) {
//此处为 js 返回的结果
}
});
}
JsBridge源码解析
JsBridge重要的三点:
- Android调用JS是通过loadUrl(url),url中可以拼接要传给JS的对象
- JS调用Android是通过shouldOverrideUrlLoading
- JsBridge将沟通数据封装成Message,然后放进Queue,再将Queue进行传输
BridgeWebview
- queueMessage()消息队列方法
- 先判断startMsg数组
- 这边startMsg是在js界面还未加载完,之前调用的消息
- 在onpageFinish()会将所有消息分发,并将startMsg致空
- init()方法
- 设置了默认的setWebViewClient()
- 监听了加载的url,重新了shouldOverrideUrlLoading()方法
- 在页面onPageFinish()加载结束的时候
- 向js中注入一端js代码(WebViewJavascriptBridge.js)
- 判断当前webview中是否有未分发出去的msg,分发出去,并致空
- 设置了默认的setWebViewClient()
- 先判断startMsg数组
- bridgeWebview中有两个map
- Map<String, CallBackFunction> responseCallbacks
- 存放callbackId 和CallBackFunction 回调处理方法
- js结果返回处理
- Map<String, BridgeHandler> messageHandlers
- 存放handleName和handle处理方法
- 提供给js调用的
- Map<String, CallBackFunction> responseCallbacks
WebViewJavascriptBridge.js
- 主要的作用是向window中添加WebViewJavascriptBridge对象
- 提供给html界面的调用
- 创建了一个WebViewJavascriptBridgeReady完成事件
- document.createEvent('Events');
- 在WebViewJavascriptBridge.js加载完成的时候分发事件
Java调用JS流程
- Java层,bridgeWebview先设置好默认参数
- 设置setDefaultHandler() 设置默认没有handleName的返回处理
- 加载url
- webview.registerHandler() 注入方法提供给js调用
- Js层
- 在demo.html中 添加了connectWebViewJavascriptBridge方法
- 第一次加载的时候,获取不到WebViewJavascriptBridge
- 添加事件(WebViewJavascriptBridgeReady)bridge完成事件
- 在WebViewJavascriptBridge.js完成,发出完成事件的时候,重新处理callback
- 在收到事件重新处理callBack的时候WebViewJavascriptBridge不为空
- callBack中主要做俩大事情
- bridge.init()
- 添加js端默认的messageHandler消息处理
- 这个处理和java webview中的ponpageFinish()一样
- bridge.registerHandler()
- 向bridge中注入方法提供给java调用
- bridge.init()
- 第一次加载的时候,获取不到WebViewJavascriptBridge
- 在demo.html中 添加了connectWebViewJavascriptBridge方法
- 至此,两端的通信才算建立完成
Java调用JS流程
- webview.callHandler()
- 内部会调用doSend()
- 根据handleName、data、callback组装出msg
- 创建一个callbackId ,将id和callBackFunction存放在map中
- msg中也存入一份callbackId
- 发送消息
- 在主线程中调用 webview.loadUrl()调用js代码
- 内部会调用doSend()
- js中的WebViewJavascriptBridge.js
- _handleMessageFromNative()方法会接受到调用的msg
- 在js中根据handleName去除对应的handle做处理
- 处理结束将responseId:callbackId 和结果一起返回
- 根据双方有responseId 和 callbackId 判断是发送还是请求