Hybrid架构:WebView中的Hybrid(JsBridge等)demo,WebViewClient和WebChromeClient及安全漏洞,Js与Native通信

-- WebView形象的理解上述流程从一个loadUrl来看,详细流程如下:
Browser.loadUrl->WebView.loadUrl->WebViewChromium.loadUrl->AwContents.loadUrl->ContentViewCore.loadUrl。

-- webview有两个方法:setWebChromeClient 和 setWebClient:
setWebClient:主要处理解析,渲染网页等浏览器做的事情,WebViewClient就是帮助WebView处理各种通知、请求事件的;
setWebChromeClient:辅助WebView处理Javascript的对话框,网站图标,网站title,加载进度等。

android WebView详解,常见漏洞详解和安全源码- https://blog.csdn.net/self_study/article/details/54928371
Android基于JsBridge封装的高效带加载进度的WebView- https://blog.csdn.net/sk719887916/article/details/52402470
Android中WebView的JavaScript代码和本地代码交互的三种方式- https://blog.csdn.net/jiangwei0910410003/article/details/52687530

腾讯正式开源高性能Hybrid框架VasSonic- https://github.com/Tencent/vassonic

--  在PC端用谷歌浏览器调试android webView中的html页面:https://blog.csdn.net/qq229466182/article/details/78708595
 首先,此处的html页面是指在webView加载运行的。 
android在4.4版本及以上,使用了Chromium作为webView的内核支持,这也使得我们
可以在pc端的chrome浏览器对运行在webView里的html进行调试,首先要在webView设置中加如下代码
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT){       
   webView.setWebContentsDebuggingEnabled(true); 
}

chrome://inspect/#pages

> Js与Native通信
- Js通知Native目前有三种方案。
 1.API注入。通过webview.addJavascriptInterface()的方法实现。
 2.拦截Js的alert/confirm/prompt/console等事件。由于prompt事件在js中很少使用,所以一般是拦截该事件。这些事件在WebChromeClient都有对应的方法回调(onConsoleMessage,onJsPrompt,onJsAlert,onJsConfirm)
 3.url跳转拦截,对应WebViewClient的shouldOverrideUrlLoading()方法。
  第一种方法,由于webview在4.2以下的安全问题,所以有版本兼容问题。后两种方法原理本质上是一样的,都是通过对webview信息冒泡传递的拦截,通过定制协议-拦截协议-解析方法名参数-执行方法-回调。

- Native通知Js
webview可以通过loadUrl()的方法直接调用。在4.4以上还可以通过evaluateJavascript()方法获取js方法的返回值。
4.4以前,如果想获取方法的返回值,就需要通过上面的对webview信息冒泡传递拦截的方式来实现。

> Hybrid App

-- MUI 框架 :https://github.com/dcloudio/mui ;html+css+js就能开发app的框架
  MUI,react native对比有什么区别?react native只使用js,而Mui这套使用的是html+css+js。两者区别最大是no HTML5 和 h5+。这点对于渲染方式要及其大的区别。react native也就是使用js语言编程,但不使用浏览器引擎渲染,而是用独立v8引擎解析指定的js语法,然后由js操作绘制界面。而h5+主要就是靠webview来渲染html界面的。这个渲染方面的区别,还有就是react native是学一套做一套模式,这点就是学ios写ios app,学andriod写android app。这点和Mui app一套双平台,有所区别。
  MUI,superwebview对比有什么区别?之前看到我国开发的另一款 Hybrid App 框架,api不够Mui的多,社区活跃度差点。但我有空也会用它来重构一下,支持一下我国开发项目。

MUI蓝牙打印(Android)- https://blog.csdn.net/mss359681091/article/details/82111872

-- SuperWebView 记录 遇到的问题解决方案-https://www.jianshu.com/p/838f193fb7d9
APICloud SuperWebView融合Android原生平台- https://blog.csdn.net/MeetYourMaster/article/details/81137344

-- JsBridge 混合开发

WebView中的网页进行交互,点击网页通过接口进行原生处理,
Android中使用WebView与JS交互全解析- http://blog.csdn.net/u012124438/article/details/53371102
Android中使用WebView与JS交互全解析- http://blog.csdn.net/jdsjlzx/article/details/51376739
为WebView中的Java与JavaScript提供【安全可靠】的多样互通方案- https://github.com/pedant/safe-java-js-webview-bridge

关于腾讯浏览器服务Android X5WebView的Demo- https://github.com/EUEHBin/X5WebViewDemo

-- 基于https://github.com/lzyzsd/JsBridge 优化改进而来的Android JsBridge
1.基于系统的JsBridge; 2.基于Tbs X5内核的JsBridge 

优化改进而来的Android JsBridge- https://github.com/hjhrq1991/JsBridge

-- (推荐)H5与原生通信,JsBridge- https://github.com/lzyzsd/JsBridge

if (callback != null) {
 myInterface.addCallback(++uniqueId + "", callback);
 webView.loadUrl("javascript:window." + kInterface+ ".onResultForScript(" + uniqueId + "," + script + ")");
} else {
 webView.loadUrl("javascript:" + script);
}

JSBridge框架,JS和native通信的桥梁- https://github.com/firewolf-ljw/WebViewJSBridge 
Android 各个版本WebView- http://blog.csdn.NET/typename/article/details/40425275
webview实现h5视频全屏播放兼容Android7.0,兼容全部版本-http://blog.csdn.net/insist_hui/article/details/58172859  
Android实现微信webview兼容Android 7.0- https://github.com/lshAndroid/WebviewTBS/tree/master
JsBridge实现Js与Java的互相调用- https://github.com/lzyzsd/JsBridge 
WebViewJavascriptBridge框架- https://github.com/marcuswestin/WebViewJavascriptBridge

> 拦截网络webview URL请求
webview拦截请求- http://blog.csdn.net/knxw0001/article/details/10903055
Android 拦截WebView加载URL,控制其加载CSS、JS资源- http://blog.csdn.net/lyhhj/article/details/49517537
Android中WebView拦截js请求- http://blog.csdn.net/wang8651971/article/details/45584117

@Override
   public boolean shouldOverrideUrlLoading(WebView view, String url) {
      if (url.startsWith(kCustomProtocolScheme)) {
         if (url.indexOf(kQueueHasMessage) > 0) {
            flushMessageQueue();
         }
         return true;
      }
      return super.shouldOverrideUrlLoading(view, url);
   }

   @Override
   public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
      //TODO
      String fileName = null;
      WebResourceResponse response = null;
      if (url.contains("logo")) {
         try {
            InputStream localCopy = NyApplication.getInstance().getAssets().open("droidyue.png");
            response = new WebResourceResponse("image/png", "UTF-8", localCopy);
         } catch (IOException e) {
            e.printStackTrace();
         }
      }
      if(url.contains("/base.css")){
         LogUtil.e(",WVJBWebViewClient,shouldOverrideUrlLoading()","url="+url);
//       webView.loadUrl("file:///android_asset/pages/css/base.css");
      }else if(url.contains("/netyun/css/textitem.css")){
         LogUtil.e(",WVJBWebViewClient,shouldOverrideUrlLoading()","url="+url);
//       webView.loadUrl("file:///android_asset/pages/css/textitem.css");

      }else if(url.contains("/js/item.js")){
         LogUtil.e(",WVJBWebViewClient,shouldOverrideUrlLoading()","url="+url);
//       webView.loadUrl("file:///android_asset/pages/js/item.js");

      }else if(url.contains("/libs/requirejs/require.js")){
         LogUtil.e(",WVJBWebViewClient,shouldOverrideUrlLoading()","url="+url);
//       webView.loadUrl("file:///android_asset/pages/js/require.js");

      }else{

      }
      try {
         InputStream localCopy = NyApplication.getInstance().getAssets().open("droidyue.png");
         response = new WebResourceResponse("image/png", "UTF-8", localCopy);
      }catch (IOException e) {
         e.printStackTrace();
      }
      return response;
//    return super.shouldInterceptRequest(view, url);
   }

   @Override
   public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
      return super.shouldInterceptRequest(view, request);
   }

> WebView中WebViewClient和WebChromeClient区别与联系
-- WebViewClient和WebChromeClient
WebViewClient用于帮助WebView处理各种通知和请求事件;
WebChromeClient更丰富一些,帮助WebView处理Javascript各类对话框、弹窗等等。

Hybrid App知识点收集- http://blog.csdn.net/qq_27429143/article/details/78916163
 1.拦截JS对话框 WebView.setWebChromeClient(new WebChromeClient(){});
 2. WebView拦截某一个链接不执行此链接或拦截URL或拦截H5页面点击之后的URL

Android webView拦截url- http://blog.csdn.net/u010694658/article/details/52388287
// 此回调是拦截点击要跳转的url链接,并对请求的url链接做修改(添加删除字段)
public WebResourceResponse shouldInterceptRequest(WebView view, String url) 
// 在点击请求的是链接是才会调用,重写此方法返回true表明点击网页里面的链接还是在当前的webview里跳转,不跳到浏览器那边。这个函数我们可以做很多操作,比如我们读取到某些特殊的URL,于是就可以不打开地址,取消这个操作,进行预先定义的其他操作,这对一个程序是非常必要的。
public boolean shouldOverrideUrlLoading(WebView view, String url)

1.WebViewClient比较基础的方法,帮助WebView处理各种通知和请求事件;
//处理webView的按键事件
boolean shouldOverrideKeyEvent(WebView view, KeyEvent event)
//截取url请求,在当前视图加载,避免在跳转到自带浏览器
boolean shouldOverrideUrlLoading(WebView view, String url)
//WebView改变时调用
void onScaleChanged(WebView view, float oldScale, float newScale)
//对https的请求处理
void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error)
//获取返回信息授权
void onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler, String host, String realm)
//处理报错信息(API23以后用第二个)
void onReceivedError(WebView view, int errorCode, String description, String failingUrl)
void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error)
//页面开始载入时调用
void onPageStarted(WebView view, String url, Bitmap favicon)
//页面载入结束时调用
void onPageFinished(WebView view, String url)
//加载资源时调用
void onLoadResource(WebView view, String url)

webView.setJavaScriptEnabled(true)影响Activity的生命周期
//Agent设置
//     WebSettings webSettings = wvPagePV.getSettings();
//     wvPagePV.getSettings().setJavaScriptEnabled(true); // 支持js互调,影响Activity的生命周期
       wvPagePV.getSettings().setUserAgentString(wvPagePV.getSettings().getUserAgentString() + "/baidu.com/" + MyUtils.getVersionName(mContext));
       wvPagePV.loadUrl(newsDetail.newsUrl); 

wvPagePV.setWebViewClient(new WebViewClient(){//拦截URL请求或页面点击
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
        LogUtil.e("desaco","url="+url);
        return super.shouldOverrideUrlLoading(view, url);
    }

    @Override
    public void onPageStarted(WebView view, String url, Bitmap favicon) {
        LogUtil.e("desaco","onPageStarted()");
        super.onPageStarted(view, url, favicon);
    }

    @Override
    public void onPageFinished(WebView view, String url) {
        LogUtil.e("desaco","onPageFinished()");
        super.onPageFinished(view, url);
    }

    @Override
    public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
        super.onReceivedError(view, request, error);
    }

    @Override
    public void onReceivedClientCertRequest(WebView view, ClientCertRequest request) {
        super.onReceivedClientCertRequest(view, request);
    }
});

2.WebChromeClient比较基础的方法,帮助WebView处理Javascript各类对话框、弹窗等
//webview关闭时调用void onCloseWindow(WebView window)
//Js的弹窗boolean onJsAlert(WebView view, String url, String message, JsResult result)
//Js提示框boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result)
//Js确认框boolean onJsConfirm(WebView view, String url, String message, JsResult result)
//加载进度void onProgressChanged(WebView view, int newProgress)
//全屏模式(API18以后用第二种)onShowCustomView(View view, WebChromeClient.CustomViewCallback callback)
onShowCustomView(View view, int requestedOrientation, WebChromeClient.CustomViewCallback callback)

wvPagePV.setWebChromeClient(new WebChromeClient() {//拦截JS对话框
    @Override
    public void onProgressChanged(WebView view, int progress) {
    }

    @Override
    public void onReceivedTitle(WebView view, String title) {
        super.onReceivedTitle(view, title);
    }

    @Override
    public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
        return super.onJsAlert(view, url, message, result);
    }

    @Override
    public boolean onJsConfirm(WebView view, String url, String message, JsResult result) {
        return super.onJsConfirm(view, url, message, result);
    }

    @Override
    public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
        return super.onJsPrompt(view, url, message, defaultValue, result);
    }

    @Override
    public boolean onJsTimeout() {
        return super.onJsTimeout();
    }

    @Override
    public boolean onConsoleMessage(ConsoleMessage consoleMessage) {
        return super.onConsoleMessage(consoleMessage);
    }

    @Override
    public void onReceivedIcon(WebView view, Bitmap icon) {
        super.onReceivedIcon(view, icon);
    }
});

3. WebView未开放的重写方法,比如如下:
// For Android 3.0+ 
public void openFileChooser(ValueCallback<Uri> uploadMsg) {...} 
// For Android 3.0+ 
public void openFileChooser(ValueCallback uploadMsg, String acceptType) {...} 
// For Android 4.1 
public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) {...}
// For Android 5.0+
public boolean onShowFileChooser (WebView webView, ValueCallback<Uri[]> filePathCallback, 
WebChromeClient.FileChooserParams fileChooserParams) {
return true;  
}

4. webView的安全漏洞
webView常见漏洞以及解决方法- http://blog.csdn.net/fulai00/article/details/52921779
Android4.2下 WebView的@addJavascriptInterface漏洞解决方案- http://blog.csdn.net/zhouyongyang621/article/details/47000041
JS与WebView交互存在的一些问题- http://www.jianshu.com/p/93cea79a2443

在Android系统4.3.1~3.0版本,系统webview默认添加了searchBoxJavaBridge_接口,如果未移除该接口可能导致低版本Android系统远程命令执行漏洞;
修复建议:判断系统版本,显式调用removeJavascriptInterface方法移除searchBoxJavaBridge_接口;
// 在Android系统4.3.1~3.0版本,系统webview默认添加了searchBoxJavaBridge_接口,如果未移除该接口可能导致低版本Android系统远程命令执行漏洞
//如果真的需要没有这些漏洞的话,你可以尝试用腾讯的X5内核,和WebView用法一样。
removeJavascriptInterface("searchBoxJavaBridge_");
removeJavascriptInterface("accessibility")  ;
removeJavascriptInterface("accessibilityTraversal");

if(Build.VERSION.SDK_INT == 18){
  mWebView.removeJavascriptInterface("searchBoxJavaBridge_");
}
if (Build.VERSION.SDK_INT >= 11 && Build.VERSION.SDK_INT < 17) {
  try {
      webView.removeJavascriptInterface("searchBoxJavaBridge_");
      webView.removeJavascriptInterface("accessibility");
      webView.removeJavascriptInterface("accessibilityTraversal");
  } catch (Throwable tr) {
      tr.printStackTrace();
  }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值