在订制腾讯新闻客户端的汽车页卡时,有些页面是用HTML页面实现的。比如车系详情页,车型详情页。这类页面因为汽车运营的关系具有不定期更新的特点。比如车型降价,新车上市等。使用HTML页面之后,有些数据需要从客户端传递过来,也有一些数据需要从页面传递到客户端,也就是HTML与客户端之间通信的问题。
Android平台
Android调用JS
JS调用Android
弊端
在Android 4.2之前的版本中,通过addJavascriptInterface然后利用java的反射机制,可以回调java类中的内置静态变量。
首先,通过java可以反弹shell,这样可以读写Android文件系统。
其次,可以对网页挂马,安装apk到手机中
以上流程,可以将apk进行拆分,利用echo写入到文件系统中,然后利用adb进行安装。
在Android 4.2版本中,开始使用@JavascriptInterface,然后在java代码中验证js调用的每个参数,屏蔽攻击代码,可以防止攻击。
汽车垂直化方案
新闻客户端提供两种js调用native的方式
- url scheme方式
通过伪协议”jsbridge://get_with_json_data?json=params”, native代码重写shouldOverrideUrlLoading来做相关接口的实现和白名单控制
- prompt方式
这种方式是通过native重写onJsPrompt,拦截webview中的window.prompt并且获取其中的参数,处理完成之后需要调用JsPromptResult的confirm方法。
更多Android下js调用native的方案见此:【Android WebView】Js调用Native的四种方式
将与native通信用到的接口挂载在window.XXX下,调用window.XXX.YYY就可以调用native的方法。
iOS平台
iOS调用JS
JS调用iOS
js调用iOS,用到了开源库TGJSBridge。其基本原理是利用伪协议”jsbridge://PostNotificationWithId-“,在native代码shouldStartLoadWithRequest中捕获并解析请求,然后调用相关的native逻辑。使用流程如下。
在js调用iOS时,有一个前提,就是native代码中需要首先完成jsBridge的初始化。TGJSBridge提供了一个jsBridgeReady的事件,js端监听jsBridgeReady事件并在事件处理函数中再向native发送通知。
但是有个问题,新闻客户端将TGJSBridge.js文件打包到了安装包中,web页面无需再引入此js文件。在处理像设置页面标题这种问题时,即页面加载完成之后就需要马上向native发送通知的情况,就会有问题。
- js端直接调用jsBridge.bind(‘jsBridgeReady’)——jsBridge可能还未初始化,并不在window的context中。
- 将jsBridge初始化操作提前,放在webViewDidStartLoad——jsBridgeReady已经被触发,但是页面js端还没开始监听jsBridgeReady事件。
native与js的jsBridge初始化调用顺序相互依赖,需要处理好,才能解决像setTitle这种操作。
新闻客户端汽车页卡车系详情页的解决方式
以上流程中,各种事件的监听和触发确实比较绕。但是梳理下来,是可以保证页面标题能正常而且尽可能快的被设置的。
参考
WebView中接口隐患与手机挂马利用
【Android WebView】Js调用Native的四种方式
WebView中JavaScript与Objective-C的交互