Android WebView常见问题处理

1、Android 8.0+无法重定向

在Android8.0中,重WebViewClient时需要注意,shouldOverrideUrlLoading返回值是false才会自动重定向,并且无需调用loadUrl

@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
                  
      if(shouldLoadingUrl()) {
         view.loadUrl(url);
        return true;
      }
     return false;
}

public boolean shouldLoadingUrl() {
      /**
      * 低于android 8.0的需要手动loadURL,大于等于android 8.0直接返回false,否则无法重定向
      */
    return Build.VERSION.SDK_INT<26;
}

2、Cookie同步

2.1、场景:C/S->B/S Cookie同步

在Android混合应用开发中,一般来说,有些页面通过Native方式实现,有些通过WebView实现。对于登录而已,假设我们通过Native登录,需要把SessionID传递给WebView,这种情况需要同步。

2.2、场景:不同域名之间的Cookie同步

对于分布式应用,或者灰度发布的应用,他的缓存服务器是同一个,那么域名的切换时会导致获取不到sessionID,因此,不同域名也需要特别处理。

定义方法:

 public static void synCookies(Context context, String url) {
        try {

            if (!UserManager.hasLogin()) {  //判断用户是否已经登录
               
                setCookie(context, url, "SESSIONID", "invalid");
            } else {
                setCookie(context, url, "SESSIONID", SharePref.getSessionId());
               
            }

        } catch (Exception e) {
        }
    }

private static void setCookie( Context context,String url, String key, String value) {

             if (Build.VERSION.SDK_INT < 21) {  
                CookieSyncManager.createInstance(context);  
             }
            CookieManager cookieManager = CookieManager.getInstance();
            cookieManager.setAcceptCookie(true);  //同样允许接受cookie


            URL pathInfo = new URL(url);
            String[] whitelist = new String{".abc.com","abc.cn","abc.com.cn"}; //白名单
            String domain = null;
            
           for(int i=0;i<whitelist.length;i++){
             if(pathInfo.getHost().endsWith(whitelist[i])){
               domain  = whitelist[i];
               break;
             }
           }
            if(TextUtils.isEmpty(domain)) return; //不符合白名单的不同步cookie

            StringBuilder sbCookie = new StringBuilder();
            sbCookie.append(String.format("%s=%s", key, value));
            sbCookie.append(String.format(";Domain=%s", domain));
            sbCookie.append(String.format(";path=%s", "/"));
            String cookieValue = sbCookie.toString();
            cookieManager.setCookie(url, cookieValue);
            if (Build.VERSION.SDK_INT < 21) {  
                CookieSyncManager.getInstance().sync();  
             } else {  
               CookieManager.getInstance().flush();  
           }  
    }

调用位置:shouldOverrideUrlLoading中调用

@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
       syncCookie(view.getContext(),url);   //同步,当然还可以优化,如果前一个域名和后一个域名不同时我们再同步
      if(shouldLoadingUrl()) {
         view.loadUrl(url);
        return true;
      }
     return false;
}

2.3:场景三:从B/S->C/S

这种情况多发生于第三方登录,但是获取cookie通过CookieManager即可,但是的好时机是页面加载完成

 public void onPageFinished(WebView view, String url) {  
        CookieManager cookieManager = CookieManager.getInstance();  
        String CookieStr = cookieManager.getCookie(url);  
        LogUtil.i("Cookies", "Cookies = " + CookieStr);  
        super.onPageFinished(view, url);  
    }  

注意:在页面加载之前一定要调用cookieManager.setAcceptCookie(true);  允许接受cookie,否则可能产生问题。

3、跨域访问问题

3.1访问方式

跨域访问一般来说具有一定的风险,在Android Webview中,跨域访问的方式和web 浏览器类似

  • ①CORS (推荐)
  • ②JSONP(推荐)
  • ③Cookie子域名+根目录
  • ④WebSocket
  • ⑤postMessage
  • ⑥通过后端代理
  • ⑦android内置方式

在Android中,也可以通过设置Webview方式,但是这种风险很高,最好做白名单处理,一般而言并不推荐

  /**
     * 是否允许跨域访问
     * @param settings WebSettings
     * @param isAllow
     */
    public static void allowUniversalAccessFromFileURLs(WebSettings settings,boolean isAllow){

        if(Build.VERSION.SDK_INT>=16)
        {
            settings.setAllowUniversalAccessFromFileURLs(isAllow);
        }else{
            try {
                Class<?> clazz = settings.getClass();
                Method method = clazz.getMethod("setAllowUniversalAccessFromFileURLs", boolean.class);
                if (method != null) {
                    method.invoke(settings, isAllow);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

3.2、跨域Cookie同步问题

以上方式根据情况而定,但是Cookie跨域同步,以上方式中从兼容性和安全性上,CORS相对较好。

在响应头服务器返回中,需要添加

Access-Control-Allow-Credentials:true

客户端调用时,需要设置credentials

$.ajax({
   url: a_cross_domain_url,
   xhrFields: {
      withCredentials: true
   }
});

4、安全问题

①防止XSS

②android 4.2之前的版本不要使用javainterface,可使用拦截prompt的方式

③移除android 4.2之前的默认接口

removeJavascriptInterface(“searchBoxJavaBridge_”)

removeJavascriptInterface(“accessibility”)

removeJavascriptInterface(“accessibilityTraversal”)

④防止不安全的访问

setAllowFileAccessFromFileURLs(false);

setAllowUniversalAccessFromFileURLs(false);

⑤使用https或者http2.0交互

⑥避免使用代理

5、H5布局问题

布局不要让webview滚动,推荐flex或者columns布局

猜你喜欢

转载自my.oschina.net/ososchina/blog/1647280