项目中遇到的webview的相关问题

来源:互联网 发布:linux ssh ip 编辑:程序博客网 时间:2024/05/16 18:48

1.webview的shouldOverrideUrlLoadingshouldInterceptRequest的使用:

  shouldOverrideUrlLoading常用来做劫持处理,主要劫持的是url。

(1)这个方法的功能显而易见,我们可以通过该方法来实现web和native的交互。比如拦截固定host的url,来做具体的native操作。

(2)这个方法也可以用来过滤白名单。防止恶意攻击。恶意攻击一般分为两种,外部调起时传入加载url,如果被第三方换成他们的url,有可能就会被攻击。另外是数据拦截,把页面替换成他们的页面,也可能被攻击。我们过滤白名单一般可以通过过滤域名来判断是否可以加载。如果不是我们内部页面可以给用户以提示。

(3)这个方法在手动调用WebView.loadUrl(url);时是不会被调用的,再进一步点击才会走这个方法。这点要注意。所以上边的白名单过滤的时候,也要在loadUrl时加判断

 shouldInterceptRequest主要是资源过滤。

(1)这里我们常用作资源的缓存处理,比如图片的异步加载,js,css和图片等做缓存处理。

(2)如果对资源要求比较严格,比如要进行资源的白名单校验时,可以把白名单写到这个方法里。

2.WebViewClient的使用:

onPageStarted,onPageFinished,onReceivedError,onReceivedSslError这几个方法是我们经常用的一套加载处理。

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
public class MyWebViewClient extends WebViewClient {
        @Override        public void onPageStarted(WebView view, String url, Bitmap favicon) {            // TODO Auto-generated method stub            super.onPageStarted(view, url, favicon);            showLoading();//显示加载页面         }        @Override        public boolean shouldOverrideUrlLoading(WebView view, String url) {            mFail = false            try {                if (url.startsWith("http:") || url.startsWith("https:") || url.startsWith("file:")) {                    return handleWebRequest(url);//处理网络请求                }                view.getContext().startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url)));//其他情况由系统自己处理,比如打电话等操作,直接调用系统方法                return true;            }catch(Exception e){                Log.e(TAG,e+"");            }            return false;        }        private boolean handleWebRequest(String url){            //如果当前页面的加载地址为默认地址,则直接交给系统webView去loadurl即可            if (url.equals(mLoadUrl)) {                return false;            else {              //url拦截,如果是调起native的要交由native处理                Uri uri = Uri.parse(url);                String host = uri.getHost();                String path = uri.getPath();                String params = uri.getQuery();                if (ConstantConfig.FE_HOST.equals(host) && mInterceptPath.containsKey(path)) {                    handleIntercept(path, params);                    return true;                                return false;            }        }        private void handleIntercept(String path, String params) {            String nativePath = mInterceptPath.get(path);            mJsInterface.dealAction("jump", nativePath, params);        }               @Override        public void onPageFinished(WebView view, String url) {            String title = view.getTitle();            if(title!= null && title.contains("Error report")){//解决502页面显示                mFail = true;            }            if (!mFail) {                                           showNormal();            }else{                showFail();                            @Override        public void onReceivedError(WebView view, int errorCode, String description,                                    String failingUrl) {            mFail = true;            showFail();          //处理证书异常,拦截ssl请求错误        @Override        public void onReceivedSslError(WebView view,                                       SslErrorHandler handler, SslError error) {//            handler.proceed();            super.onReceivedSslError(view, handler, error);            mFail = true;            showFail();            String msg = "您访问的页面SSL证书异常";            mLoadingView.statusToFail(msg);            }


3.webview与native交互

由于4.4之前addJavascriptInterface的调用存在注入风险。所以为了兼容老版本,我们要考虑更安全的方式。

(1)上边用shouldOverrideUrlLoading拦截的方式,是web与native交互时较为安全的方式之一。
(2)另外一种方式就是通过调用调用onJsPrompt的方式。

这种方式的实现方式如下:
我们与server商定协议如下:myscheme://myhost/mypath?params={key=value}的格式
用scheme来区分是否是我们的应用,myhost和path来区分具体的调起内容,params来携带具体的参数。
然后我们就可以在js中调用window.prompt(协议内容)的形式,来调起我们native的操作了。
public class MyWebChromeClient extends WebChromeClient {        @Override        public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {                      String scheme = getResources().getString(R.string.qiangui_intercept_scheme);            if (!TextUtils.isEmpty(message) && message.startsWith(scheme)) {                result.confirm();                Uri uri = Uri.parse(message);                String actionType = uri.getHost();                String path = uri.getEncodedPath();                String pathStr = null;                if (!TextUtils.isEmpty(path)) {                    pathStr = path.substring("/".length());                }                String queryParams = uri.getQuery();                String actionContent = null;                if (queryParams != null) {                    actionContent = queryParams.substring("params=".length());                }                mJsInterface.dealAction(actionType, pathStr, actionContent); //具体的native处理                              return true;            }            return super.onJsPrompt(view, url, message, message, result);        }    }


4.WebView设置Cookie


注意:WebView的cookie是共享的,一个进程里只需要放一份,所有的cookie就是共享的了。

  在Android应用程序中经常会加载一个WebView页,如果需要客户端向WebView传递信息,比如Cookie,也是可以的。

需要应用程序先将Cookie注入进去,打开该网页时,WebView会将加载的url通过http请求传输到服务器。同时,在这次请求中,会将Cookie信息通过http header传递过去。

    流程如下:

    1、客户端通过以下代码设置cookie   

1
2
3
4
5
6
public static void synCookies(Context context, String url) {  
         CookieSyncManager.createInstance(context);  
         CookieManager cookieManager = CookieManager.getInstance();
         cookieManager.setCookie(url, "uid=1243432");                                              
         CookieSyncManager.getInstance().sync(); 
 }

2、CookieManager会将这个Cookie存入该应用程序/data/data/databases/目录下的webviewCookiesChromium.db数据库的cookies表中

   3、打开网页,WebView从数据库中读取该cookie值,放到http请求的头部,传递到服务器

   4、客户端可以在注销登录时清除该应用程序用到的所有cookies

1
2
3
4
5
6
private void removeCookie(Context context) {
        CookieSyncManager.createInstance(context);  
        CookieManager cookieManager = CookieManager.getInstance(); 
        cookieManager.removeAllCookie();
        CookieSyncManager.getInstance().sync();  
}

5.WebView添加header:

处理WebView中的非超链接请求(如Ajax请求): 

有时候需要加上请求头,但是非超链接的请求,没有办法再shouldOverrinding中拦截并用webView.loadUrl(String url,HashMap headers)方法添加请求头。其他ajax请求参见:http://blog.csdn.net/u011127787/article/details/41042597

cookie和header的使用场景参见下文:

http://blog.csdn.net/t12x3456/article/details/17385263/

6.WebView加载https 的url时,在fiddler调试过程中有证书的问题。如果想要跨过证书这一步,可以利用请求ip:端口的方式,在本地下载证书。
第二种方式是在代码中处理

将handler.proceed()注释去掉,将下边的代码注释掉即可。

1 0
原创粉丝点击