您的位置:首页 > 移动开发

WebView中addJavascriptInterface接口的隐患解决方案

2017-05-10 10:08 489 查看
我们很多时候要使用WebView来展示一个网页,现在很多应用为了做到服务端可控,很多结果页都是网页的,而不是本地实现,这样做有很多好处,比如界面的改变不需要重新发布新版本,直接在Server端修改就行了。用网页来展示界面,通常情况下都或多或少都与Java代码有交互,比如点击网页上面的一个按钮,我们需要知道这个按钮点击事件,或者我们要调用某个方法,让页面执行某种动作,为了实现这些交互,我们通常都是使用JS来实现,而WebView已经提供了这样的方法,具体用法如下:

[java] view
plain copy

mWebView.getSettings().setJavaScriptEnabled(true);  

mWebView.addJavascriptInterface(new JSInterface(), "jsInterface");  

我们向WebView注册一个名叫“jsInterface”的对象,然后在JS中可以访问到jsInterface这个对象,就可以调用这个对象的一些方法,最终可以调用到Java代码中,从而实现了JS与Java代码的交互。

但是用addJavascriptInterface可能导致不安全,因为JS可能包含恶意代码。

假如我们自己没有添加addJavascriptInterface,甚至默认为false呢。?还是有漏洞!因为在低于API17的WebView上默认添加"searchBoxJavaBridge_"到mJavaScriptObjects中。

        这样就有可能通过用户信任的客户端获取SD卡的数据。

        解决方法有几点:

        1. 过滤本地文件的访问: 

[java] view
plain copy

if (!url.startsWith("file://")) {  

        // to do.  

}  



        2. 过滤未知网站(可以非本站点的都不允许加载)

        3. 删除默认添加的"searchBoxJavaBridge_"

[java] view
plain copy

// in WebView setting:  

        if (Build.VERSION.SDK_INT > 10&&Build.VERSION.SDK_INT < 17) {  

            fixWebView();  

        }  

  

// fixWebView like this:  

    @TargetApi(11)  

    private void fixWebView() {  

            //        http://50.56.33.56/blog/?p=314  

            //        http://drops.wooyun.org/papers/548  

            // We hadn't use addJavascriptInterface, but WebView add "searchBoxJavaBridge_" to mJavaScriptObjects below API 17 by default:  

            // mJavaScriptObjects.put(SearchBoxImpl.JS_INTERFACE_NAME, mSearchBox);  

            mWebView.removeJavascriptInterface("searchBoxJavaBridge_");  

    }  

    4.(prompt()$onJsPrompt()/confirm()$onConfirm()/alert()$onAlert()):

继承该WebChromeClient重写以上三个


方法其中一个的具体实现

class HarlanWebChromeClient extends WebChromeClient {

/*此处覆盖的是javascript中的alert方法。
*当网页需要弹出alert窗口时,会执行onJsAlert中的方法
* 网页自身的alert方法不会被调用。
*/
@Override
public boolean onJsAlert(WebView view, String url, String message,
JsResult result) {
show("onJsAlert");
result.confirm();
return true;
}

/*此处覆盖的是javascript中的confirm方法。
*当网页需要弹出confirm窗口时,会执行onJsConfirm中的方法
* 网页自身的confirm方法不会被调用。
*/
@Override
public boolean onJsConfirm(WebView view, String url,
String message, JsResult result) {
show("onJsConfirm");
result.confirm();
return true;
}

/*此处覆盖的是javascript中的confirm方法。
*当网页需要弹出confirm窗口时,会执行onJsConfirm中的方法
* 网页自身的confirm方法不会被调用。
*/
@Override
public boolean onJsPrompt(WebView view, String url,
String message, String defaultValue,
JsPromptResult result) {
show("onJsPrompt....");
result.confirm();
return true;
}


然后给webView设置该重写的类
//设置ChromeClient
mWebView.setWebChromeClient(new HarlanWebChromeClient());


相应的在JS中的具体实现代码如下

function cfm() {
confirm("")
}

function pmt() {
prompt("","");
}

function onAlert()
{
alert("这是网页中的alert方法,如果重写了mWebView的onAlert方法,该方法不会执行");
}


触发页面中的js函数,例如:

<p><input type="button" onclick="cfm()" value="Confirm"/></p>
<p><input type="button" onclick="pmt()" value="Prompt"/></p>
<p><input type="button" onclick="onAlert()" value="Alert"/>


实现原理就是在页面中触发的方法被webView中设置的WebChromeClient给拦截了,从而执行了WebChromeClient中重写的onXxx()方法, 没有执行页面中相应的onXxx()方法,这是方式相对简单,而且安全。

参考链接: https://github.com/Sunzxyong/RainbowBridge

   http://blog.csdn.net/owillll/article/details/20996139
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: