整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          「WWDC2018」-Web安全策略

          「WWDC2018」-Web安全策略

          eb安全策略

          web安全對iOS開發者來說重要嗎?重要!APP中通常會使用很多web頁面,例如廣告、登錄流程、閃屏,或者需要使用跨平臺功能的時候。你可能在頁面中僅僅一部分使用web,也可以整個頁面都是webView,甚至做一個web app。因此web安全對于app來說非常重要。

          來自web的安全攻擊有以下幾種:

          • 跨域攻擊
          • 預測執行攻擊
          • 窗口控制攻擊

          本文將針對這三種攻擊類型,給出安全防御措施。

          安全傳輸

          網絡傳輸相信大家都很熟悉了,安全的傳輸能夠保證接收到的數據來自可信任的站點,并且在傳輸工程中不會被篡改。安全傳輸是其它安全措施的基礎,采取的措施包括:

          • HTTPS和WSS(webSocket Secure)
          • Http Strict Transport Security(HSTS)遵循HTTPS安全協議的web只能訪問同樣遵循HTTPS安全協議的內容,不能訪問遵循HTTP不安全協議的內容。
          • Upgrade-Insecure-Requests 請求頭中添加這一項表示web支持更加安全的升級機制,服務器可以重定向到這個站點的安全版本。
          • 使用cookie確保安全,cookie只能被安全的傳輸,例如千萬不要把cookie放到粘貼板上
          • 在app的info.plist文件中

          Allow Arbitrary Loads in Web Content 這個開關一定要置為 NO!

          跨域封鎖

          web的內容可以來自任何站點,例如,webView上的一張圖片可以來自任何服務器,也可以從任意服務器上加載一個腳本或iframe。需要注意的是要當心來自其它服務器的資源。跨域的保護已經有20多年的歷史,并且形成了基本原則--同源策略:只有和頁面來源相同的腳本才會被該頁面執行。例如iframe來自不同的域名,同源策略不允許加載這個iframe。僅僅靠同源策略還是不夠的,還需要采取其它的防御措施。

          1. Subresource Integrity

          服務器可能會發生異常導致下發錯誤的資源使得web發生crash,但是開發者通常是知道所要請求哪個資源的,在腳本里面增加一個檢查簽名。如果簽名匹配則認為是下發了正確的資源,如果不匹配仍然可以正常工作,此時嘗試從頁面的資源里查找或者從自己的服務器重新加載。這樣做雖然降低了性能,但是提升了安全性。

          <script src="https://cdn.example/framework.js"
           integrity="sha256-8WqyJLuWKRB...oZkCnxQbWwJVw=">
          </script>
          window.framwork || // reload from own domain
          

          2. Content Security Policy

          HTTP response:
          :status:200
          Content-Security-Policy:
           default 'self'; // No inline
           script-src cdn.example;
           frame-src social.example;
           frame-ancestors news.example;
          

          HTTP response的Header里面,default設置成自己,默認只能加載同源的資源;script-src和frame-src 分別指定可信任的腳本和iframe的來源;frame-ancestor設置成news.example,指定只有news.example可以iframe我們的web。

          另外不使用inline屬性的腳本也是一種防御措施,不使用inline腳本,只從文件加載腳本,這么做分離了邏輯和文件,更加安全。

          3. HttpOnly cookies

          HTTPOnly cookies作為一種安全措施,已經有至少15年的使用歷史。在這之前script通過document.cookie這個強大的api能拿到文檔的cookie,留下安全隱患。HTTPOnly cookies能夠阻止這種情況,只允許HTTP請求訪問cookie,禁止使用script訪問cookie。它的使用方式很簡單,只需要在HTTP response的Header里面加上HttpOnly這一項,如下

          HTTP response:
          :status:200
          Set-Cookie:
           auth=abc...123; HttpOnly;
          

          4. SameSite cookies

          在HTTP response的Header里面將SameSite cookies這一項設置為Strict,那么將不允許把cookie從一個域名發送到另一個域名。例如其他人的web里面嵌入了我們的web,如果我們的服務器HTTP response的Header里面SameSite cookies=Strict,那么其他人將無法使用他的cookie來訪問我們的服務器。

          HTTP response:
          :status:200
          Set-Cookie:
           auth=abc...123; HttpOnly;
           SameSite=strict
          

          5. Cross-Origin-Resource-Policy

          Cross-Origin-Resource-Policy是推出的新功能。之前web可以加載任意web中的資源,例如圖片或者script。在HTTP response的Header里面將Cross-Origin-Resource-Policy這一項設置為Same,將不允許別人的web向我們的服務器請求圖片或者script,但是我們自己的web可以。

          HTTP response:
          :status:200
          Cross-Origin-Resource-Policy:Same
          

          6. Cross-Origin-Window-Policy

          Cross-Origin-Window-Policy也是新推出的功能。之前通過window.open這個強大的api,其他人的web可以在新窗口中打開我們域名下的web,通過一些手段可以修改我們的web,導航到攻擊者指定的頁面。在HTTP response的Header里面將Cross-Origin-Resource-Policy這一項設置為Deny,將阻止其他人修改我們web中的內容,當然別人仍然還是可以打開我們的web。Cross-Origin-Resource-Policy適用于希望使用post message 進行窗口間通信,但是不想讓別人控制我們自己web內容的情況。

          HTTP response:
          :status:200
          Cross-Origin-Window-Policy:Deny
          

          常見的web攻擊及防御手段

          Cross-Origin Attacks

          • Cross-Site Scripting
          • Compromised CDN
          • Cross-Site Request Forgeries

          Cross-Site Scripting

          例如我們的web里面有一個文本框,用戶可以輸入文字,如下圖。假如攻擊者注入了這么一段腳本,如果沒有采取防御措施,那么我們web的cookie就會被盜取。

          在HTTP response的Header中添加HTTPOnly這一項,就能阻止腳本訪問文檔的cookie,從而防御跨域腳本攻擊。

          另外一種防御手段是Content-Security-Policy,如下

          HTTP response:
          :status:200
          Content-Security-Policy:
           default-src 'self'; // No inline
          

          Content-Security-Policy能保證拒絕加載外部來源的腳本,并且不使用inline屬性的腳本,只從文件中加載腳本。

          Compromised CDN

          例如我們的web需要從某個外部資源裝載一個framework,攻擊者可能攔截這個請求,并把它重定向到自己的攻擊腳本上,如下圖

          使用Content-Security-Policy中script-src這個屬性可以指定信任的腳本來源,并且在引用資源的時候指定來源和校驗簽名,如下

          在HTTP response中:

          HTTP response:
          :status:200
          Content-Security-Policy:
           default-src 'self'; 
           script-src cdn.example;
          

          在HTML中:

          <script src="https://cdn.example/framework.js"
           integrity="sha256-8WqyJLuWKRB...oZkCnxQbWwJVw=">
          </script>
          window.framwork || // reload from own domain
          

          3. Cross-Site Request Forgeries

          攻擊者可能在自己的web中嵌入我們的web,然后向我們的服務器發起一個偽造的網絡請求(使用的是攻擊者網站的cookie),如下圖

          如果采取了防御措施,將HTTP response的Header里面的SameSite設置為strict,那么就會禁止攻擊者網站的cookie發動到我們的服務器上面,如下

          HTTP response:
          :status:200
          Set-Cookie:
           auth=abc...123; SameSite=strict
          

          2. Speculative execution attacks (Spectre)

          防御措施有:

          • WKWebView
          • Content Security Policy
          • HttpOnly cookies
          • SameSite cookies
          • Cross-Origin-Resource-Policy

          Speculative execution 的定義:預測執行類似于批量執行條件判斷語句,例如計算機大量執行"x是否會造成數組array越界"這條指令,就能推測出這個數組的長度,進一步推測出這個數組在內存緩沖區中的地址邊界。利用緩沖區溢出這種攻擊手段,可以向web中注入攻擊腳本。當x超過數組邊界的時候,本來應該執行越界的error回調,但是確取出了攻擊腳本并執行,造成數據泄露。顯然只靠同源策略是無法防御這種攻擊的,因為攻擊腳本和文檔處在同一個域名下,并且在同一個線程中。

          防御預測執行攻擊的方法是確保web內容和其他iframe(例如攻擊腳本)處在不同的線程中

          WKWebView

          以Safari app為例,WKWebView會單獨分離出一個NetWork線程用于處理添加cookie等邏輯,而且每個網頁處在不同的線程當中,所以evil網頁是無法通過預測執行攻擊手段攻擊我們的頁面。而且因為NetWork線程也是獨立的,所以evil網頁也無法通過預測執行攻擊手段拿到重要數據,例如cookie。

          如果使用UIWebView,所有的web包括NetWork線程都在app的同一個線程中,所以是無法防御預測執行攻擊手段的。

          Content security policy

          Content security policy的封鎖功能是處于Network線程中,和web線程是分離的,因此可以防御預測執行攻擊手段。

          例如web要加載一個廣告iframe,但是這個廣告iframe被重定向到了一個攻擊腳本,如果使用了Content security policy,如下,因為攻擊腳本不在信任的frame-src里面,所以會禁止加載。還有一種情況,攻擊者的web引入了我們的web,因為設置了frame-ancestors為none,所以會禁止攻擊者網站引入我們的web,從而防御攻擊。

          HTTP response:
          :status:200
          Content-Security-Policy:
           default-src 'self'; 
           frame-src ad.example
           social.example
           frame-ancestors 'none'
          

          HttpOnly cookies 和 SameSite cookies

          HttpOnly cookies 和 SameSite cookies的封鎖功能也是處于Network線程中,和web線程是分離的,因此可以防御預測執行攻擊手段。HttpOnly cookies能夠禁止攻擊者通過腳本拿到cookie。SameSite cookies設為strict能夠禁止cookie從一個域發送到另一個域。

          Cross-Origin-Resource-Policy

          Cross-Origin-Resource-Policy的封鎖功能也是處于Network線程中,和web線程是分離的,因此可以防御預測執行攻擊手段。Cross-Origin-Resource-Policy設置成Same能禁止攻擊者的web加載我們網站的資源。

          Window Control Attacks

          Cross-Origin-Window-Policy

          攻擊者的頁面可以通過window.open這個api在新的窗口打開我們的web,攻擊者趁我們不注意的時候,把我們的頁面導航到釣魚頁面,然后誘導用戶填寫用戶名和密碼,這樣就竊取到了用戶信息。把HTTP response Header里面的Cross-Origin-Window-Policy設置為Deny,能夠禁止攻擊者修改我們的web,這樣攻擊者就無法導航到釣魚頁面。

          總結

          每種安全措施防御的攻擊類型

          建議

          • 使用安全的網絡傳輸(例如https,wss)
          • 設置Cookies為HttpOnly和其它安全選項
          • 把UIWebView升級到WKWebView
          • 測試防御措施是否生效,web是否仍然能正常工作。安全措施都具有一定的限制功能,因此測試web是否能正常工作非常重要。例如Content-Securityp-Policy的script-src白名單里少些了一個允許的域名,那么這個域名下的web就無法正常使用了。


          WKWebView是iOS8 出來的瀏覽器控件,用來取代UIWebView.對于WKWebView與UIWebView的對比特點,這里就不過多的敘述,都算是老生常談的問題了,網上的說明也很多.近來在做Web端,需要植入移動端,并且做JS交互工作.以前寫過的JavaScript:淺談iOS與H5的交互-JavaScriptCore框架是用于UIWebView.在WKWebView并不適用了,自己做的過程中遇到一些坑,在這里總結一下,做一下記錄.

          WKWebView加載本地 html文件


          現在的項目要求就是使用存儲在本地的html文件 js文件 css文件 img圖片等文件.我使用HBuilder創建了一個Demo工程.里面包含了基本的文件以及圖片資源.如下所示.然后拖到Xcode工程中.

          然后我們把整個Html工程文件夾導入工程中.

          WKWebView 在iOS 9 有新的加載本地方法- (nullable WKNavigation *)loadFileURL:(NSURL *)URL allowingReadAccessToURL:(NSURL *)readAccessURL API_AVAILABLE(macosx(10.11), ios(9.0));.但是我看了網上有一些博客說- (nullable WKNavigation *)loadRequest:(NSURLRequest *)request;并不能加載本地html文件.其實兩者都能加載.只是需要把路徑寫對.第一個方法就不過多敘述了.網上有很多的博客.這里我就用第二個方法來看一下如何加載.

          NSString *path=[[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent:@"index.html"];

          NSURLRequest *request=[NSURLRequest requestWithURL:[NSURL fileURLWithPath:path]];

          [_mainWebView loadRequest: request];

          • 1
          • 2
          • 3

          運行效果圖如下.

          Xcode工程中 html文件 加載js文件 css文件 img文件


          上面我們加載了html.可是css樣式 .img文件和js文件都沒有加載出來.那么我們該如何解決呢?(html原始加載圖如下所示.)

          對于css文件、img文件 ,js文件我們只需要把html文件中的文件夾路徑刪除即可.如下所示.

          ???????? 注意:這里是使用的- (WKNavigation *)loadRequest:(NSURLRequest *)request;方式加載的網頁.所有如上設置即可.如果使用的是loadFileURL:(NSURL *)URL allowingReadAccessToURL:(NSURL *)readAccessURL或者loadHTMLString:(NSString *)string baseURL:(NSURL *)baseURL;都需要設置本地資源文件所對應的路徑! 我們只需要把資源文件所對應的路徑設置給readAccessURL 和 baseURL即可(). 例如下面所示.

          //假定都在工程根目錄之下.

          NSURL *baseURL=[NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]];

          [_mainWebView loadHTMLString:[self loadHtmlString] baseURL:baseURL];

          • 1
          • 2
          • 3

          對于js文件,有時候我們發現我們就算如上刪除了js文件夾的路徑依然不能使用.這是為什么呢?.這里就要去檢測查看工程的設置,是否把js文件當成一個可編譯文件使用了.我們需要把它移動到資源文件中.這樣就能正常加載了.如下圖所示.

          WKWebView中警告窗 確認面板 輸入框的顯示


          相比于UIWebView,WKWebView對警告窗 確認面板 輸入框并不能直接顯示.是通過WKUIDelegate代理方法收到對應的回調方法.如下所示.

          //接收到警告面板

          - (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler;

          //接收到確認面板

          - (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL result))completionHandler;

          //接收到輸入框

          - (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(nullable NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * _Nullable result))completionHandler;

          • 1
          • 2
          • 3
          • 4
          • 5
          • 6

          我們只需要對上面的回調方法進行實現即可實現顯示警告窗 確認面板 輸入框等需求.

          WKWebView中OC方法調用JS方法


          在WKWebView OC方法調用JS方法方法比較簡單.我們只需要使用如下方法即可.

          - (void)evaluateJavaScript:(NSString *)javaScriptString completionHandler:(void (^ _Nullable)(_Nullable id, NSError * _Nullable error))completionHandler;

          • 1

          看一下我寫的例子.在index.js中定義一個方法.方法內容為彈出一個警告框.代碼如下所示.

          function alertAction(message) {

          alert(message);

          }

          • 1
          • 2
          • 3

          然后在ViewController控制器中定義一個Button.定義它的點擊方法.代碼如下所示.

          - (UIButton *)alertButton{

          if (_alertButton==nil) {

          _alertButton=[[UIButton alloc] initWithFrame:CGRectMake(KMainWidth*0.2, KMainHeight - 60, KMainWidth * 0.6, 40)];

          _alertButton.backgroundColor=[UIColor colorWithRed:250/255.0 green:204/255.0 blue:96/255.0 alpha:1.0];

          _alertButton.layer.cornerRadius=6.0f;

          _alertButton.layer.masksToBounds=YES;

          _alertButton.titleLabel.font=[UIFont systemFontOfSize:16];

          [_alertButton setTitle:@"彈出彈窗" forState:UIControlStateNormal];

          [_alertButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];

          [_alertButton addTarget:self action:@selector(alertButtonAction) forControlEvents:UIControlEventTouchUpInside];

          }

          return _alertButton;

          }

          - (void)alertButtonAction{

          [self.mainWebView evaluateJavaScript:@"alertAction('OC調用JS警告窗方法')" completionHandler:^(id _Nullable item, NSError * _Nullable error) {

          NSLog(@"alert");

          }];

          }

          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16
          • 17
          • 18
          • 19
          • 20
          • 21
          • 22

          因為彈窗不能直接顯示.所以我們實現了對應的代理方法.如下所示.

          //接收到警告面板

          - (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler{

          UIAlertController *alert=[UIAlertController alertControllerWithTitle:@"提示" message:message preferredStyle:UIAlertControllerStyleAlert];

          UIAlertAction *action=[UIAlertAction actionWithTitle:@"ok" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {

          completionHandler();//此處的completionHandler()就是調用JS方法時,`evaluateJavaScript`方法中的completionHandler

          }];

          [alert addAction:action];

          [self presentViewController:alert animated:YES completion:nil];

          }

          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10

          這時候我們點擊按鈕就會調用對應的JS方法了.相比于JavaScriptCore框架還是非常簡單的.效果圖如下所示.

          WKWebView中JS方法調用OC方法


          上一個模塊我們看到了OC方法調用JS方法.那么JS方法調用OC方法呢?我們也只需要幾步就可以完成調用.

          第一步.我們需要在WKWebView創建的過程中初始化添加ScriptMessageHandler.(命名自定例如:currentCookies.如下所示)

          WKWebViewConfiguration *configuration=[[WKWebViewConfiguration alloc] init];

          WKUserContentController *userController=[[WKUserContentController alloc] init];

          configuration.userContentController=userController;

          _mainWebView=[[WKWebView alloc] initWithFrame:CGRectMake(0, 0, KMainWidth, KMainHeight) configuration:configuration];

          [userController addScriptMessageHandler:self name:@"currentCookies"];

          • 1
          • 2
          • 3
          • 4
          • 5

          然后實現代理方法.監聽JS的回調.為了查看效果,我們仍然使用彈窗的形式展示我們的回調信息.代碼如下所示.

          //JS調用的OC回調方法

          - (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{

          if ([message.name isEqualToString:@"currentCookies"]) {

          NSString *cookiesStr=message.body;

          NSLog(@"當前的cookie為: %@", cookiesStr);

          UIAlertController *alert=[UIAlertController alertControllerWithTitle:@"提示" message:@"JS調用的OC回調方法" preferredStyle:UIAlertControllerStyleAlert];

          UIAlertAction *action=[UIAlertAction actionWithTitle:@"ok" style:UIAlertActionStyleCancel handler:nil];

          [alert addAction:action];

          [self presentViewController:alert animated:YES completion:nil];

          }

          }

          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12

          然后在Html文件中添加點擊方法.

          <div id="button_div" onclick="buttonDivAction()">

          點擊調用OC方法

          </div>

          • 1
          • 2
          • 3

          緊接著.在js文件中實現點擊事件.這時候要注意的是ScriptMessageHandler的名稱要與上面定義的一致.

          function buttonDivAction() {

          window.webkit.messageHandlers.currentCookies.postMessage({

          "body": "buttonActionMessage"

          });

          }

          • 1
          • 2
          • 3
          • 4
          • 5

          然后我們點擊網頁中對應的div就會出現對應的彈窗.效果圖如下所示.

          并且控制臺打印信息如下所示.

          總結


          相比于UIWebView,WKWebView確實更加的方便快捷.本篇博客就到這里了.如果有任何問題,歡迎在評論區回復騷棟.感謝觀看,最后還是附上本篇博客的Demo傳送門.

          者:Mino



          1.針對加載webView中的資源時加快加載的速度優化(主要是針對圖片)

          原因:html代碼下載到WebView后,webkit開始解析網頁各個節點,發現有外部樣式文件或者外部腳本文件時,會異步發起網絡請求下載文件,但如果在這之前也有解析到image節點,那勢必也會發起網絡請求下載相應的圖片。在網絡情況較差的情況下,過多的網絡請求就會造成帶寬緊張,影響到css或js文件加載完成的時間,造成頁面空白loading過久。

          解決方法:告訴WebView先不要自動加載圖片,等頁面finish后再發起圖片加載。

          //設置是否開啟密碼保存功能,不建議開啟,默認已經做了處理,存在盜取密碼的危險
          WebView.setSavePassword(false);


          2.WebView硬件加速導致頁面渲染閃爍

          原因:4.0以上的系統我們開啟硬件加速后,WebView渲染頁面更加快速,拖動也更加順滑。但有個副作用就是,當WebView視圖被整體遮住一塊,然后突然恢復時(比如使用SlideMenu將WebView從側邊滑出來時),這個過渡期會出現白塊同時界面閃爍。

          解決方法:是在過渡期前將WebView的硬件加速臨時關閉,過渡期后再開啟。

          /**
           * 請求網絡出現error
           * @param view                              view
           * @param errorCode                         錯誤
           * @param description                       description
           * @param failingUrl                        失敗鏈接
           */
          @Override
          public void onReceivedError(WebView view, int errorCode, String description, String
                  failingUrl) {
              super.onReceivedError(view, errorCode, description, failingUrl);
              if (errorCode==404) {
                  //用javascript隱藏系統定義的404頁面信息
                  String data="Page NO FOUND!";
                  view.loadUrl("javascript:document.body.innerHTML=\"" + data + "\"");
              } else {
                  if (webListener!=null){
                      webListener.showErrorView();
                  }
              }
          }
          
          // 向主機應用程序報告Web資源加載錯誤。這些錯誤通常表明無法連接到服務器。
          // 值得注意的是,不同的是過時的版本的回調,新的版本將被稱為任何資源(iframe,圖像等)
          // 不僅為主頁。因此,建議在回調過程中執行最低要求的工作。
          // 6.0 之后
          @Override
          public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
              super.onReceivedError(view, request, error);
              if (Build.VERSION.SDK_INT >=Build.VERSION_CODES.M) {
                  X5WebUtils.log("服務器異常"+error.getDescription().toString());
              }
              //ToastUtils.showToast("服務器異常6.0之后");
              //當加載錯誤時,就讓它加載本地錯誤網頁文件
              //mWebView.loadUrl("file:///android_asset/errorpage/error.html");
              if (webListener!=null){
                  webListener.showErrorView();
              }
          }
          
          /**
           * 這個方法主要是監聽標題變化操作的
           * @param view  view
           * @param title 標題
           */
          @Override
          public void onReceivedTitle(WebView view, String title) {
              super.onReceivedTitle(view, title);
              if (title.contains("404") || title.contains("網頁無法打開")){
                  if (webListener!=null){
                      webListener.showErrorView();
                  }
              } else {
                  // 設置title
              }
          }


          3.可以提前顯示加載進度條

          原因:WebView.loadUrl("url") 不會立馬就回調 onPageStarted 或者 onProgressChanged 因為在這一時間段,WebView 有可能在初始化內核,也有可能在與服務器建立連接,這個時間段容易出現白屏,白屏用戶體驗是很糟糕的。

          解決方法:提前顯示進度條雖然不是提升性能 , 但是對用戶體驗來說也是很重要的一點。

          /**
           * 在加載資源時通知主機應用程序發生SSL錯誤
           * 作用:處理https請求
           * @param view   view
           * @param handler  handler
           * @param error   error
           */
          @Override
          public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
              super.onReceivedSslError(view, handler, error);
              if (error!=null){
                  String url=error.getUrl();
              }
              //https忽略證書問題
              if (handler!=null){
                  //表示等待證書響應
                  handler.proceed();
                  // handler.cancel();      //表示掛起連接,為默認方式
                  // handler.handleMessage(null);    //可做其他處理
              }
          }


          4.WebView密碼明文存儲漏洞優化

          原因:WebView 默認開啟密碼保存功能 mWebView.setSavePassword(true),如果該功能未關閉,在用戶輸入密碼時,會彈出提示框,詢問用戶是否保存密碼,如果選擇”是”,密碼會被明文保到 /data/data/com.package.name/databases/webview.db 中,這樣就有被盜取密碼的危險。

          解決方法:通過 WebSettings.setSavePassword(false) 關閉密碼保存提醒功能。

          @Override
          protected void onDestroy() {
              try {
                  //有音頻播放的web頁面的銷毀邏輯
                  //在關閉了Activity時,如果Webview的音樂或視頻,還在播放。就必須銷毀Webview
                  //但是注意:webview調用destory時,webview仍綁定在Activity上
                  //這是由于自定義webview構建時傳入了該Activity的context對象
                  //因此需要先從父容器中移除webview,然后再銷毀webview:
                  if (webView !=null) {
                      ViewGroup parent=(ViewGroup) webView.getParent();
                      if (parent !=null) {
                          parent.removeView(webView);
                      }
                      webView.removeAllViews();
                      webView.destroy();
                      webView=null;
                  }
              } catch (Exception e) {
          
              }
              super.onDestroy();
          }


          5.自定義加載異常error的狀態頁面,比如下面這些方法中可能會出現error

          原因:當WebView加載頁面出錯時(一般為404 NOT FOUND,Android WebView會默認顯示一個出錯界面。當WebView加載出錯時,會在WebViewClient實例中的onReceivedError(),還有onReceivedTitle方法接收到錯誤。

          解決方法:自定義錯誤頁面樣式。

          @Override
          public void onPageStarted(WebView view, String url, Bitmap favicon) {
              super.onPageStarted(view, url, favicon);
              String host=Uri.parse(url).getHost();
              if (!BuildConfig.IS_DEBUG) {
                  if (Arrays.binarySearch(domainList, host) < 0) {
                      //不在白名單內,非法網址,這個時候給用戶強烈而明顯的提示
                  } else {
                      //合法網址
                  }
              }
          }


          6. WebView加載證書錯誤

          原因:webView加載一些別人的url時候,有時候會發生證書認證錯誤的情況。

          解決方法:要將正常的呈現頁面給用戶,我們需要忽略證書錯誤,需要調用WebViewClient類的onReceivedSslError方法,調用handler.proceed()來忽略該證書錯誤。

           //在onResume里面設置setJavaScriptEnabled(true)。
              @Override
              protected void onResume() {
                  super.onResume();
                  if (mWebView !=null) {
                  mWebView.getSettings().setJavaScriptEnabled(true);
                  }
              }
          //在onStop里面設置setJavaScriptEnabled(false);
              @Override
              protected void onStop() {
                  super.onStop();
                  if (mWebView !=null) {
                  mWebView.getSettings().setJavaScriptEnabled(false)
                 }
            }


          7.WebView音頻播放銷毀后還有聲音

          原因:WebView頁面中播放了音頻,退出Activity后音頻仍然在播放。

          解決方法:需要在Activity的onDestory()中從父容器中移除WebView。

          @Override
          protected void onDestroy() {
              try {
                  //有音頻播放的web頁面的銷毀邏輯
                  //在關閉了Activity時,如果Webview的音樂或視頻,還在播放。就必須銷毀Webview
                  //但是注意:webview調用destory時,webview仍綁定在Activity上
                  //這是由于自定義webview構建時傳入了該Activity的context對象
                  //因此需要先從父容器中移除webview,然后再銷毀webview:
                  if (webView !=null) {
                      ViewGroup parent=(ViewGroup) webView.getParent();
                      if (parent !=null) {
                          parent.removeView(webView);
                      }
                      webView.removeAllViews();
                      webView.destroy();
                      webView=null;
                  }
              } catch (Exception e) {
          
              }
              super.onDestroy();
          }


          8.如何設置白名單操作

          原因:客戶端內的WebView都是可以通過客戶端的某個schema打開的,而要打開頁面的URL很多都并不寫在客戶端內,而是可以由URL中的參數傳遞過去的。上面4.0.5 使用scheme協議打開鏈接風險已經說明了scheme使用的危險性。

          解決方法:設置運行訪問的白名單,或者當用戶打開外部鏈接前給用戶強烈而明顯的提示。設置白名單操作其實和過濾廣告是一個意思,這里你可以放一些合法的網址允許訪問。

          @Override
          public void onPageStarted(WebView view, String url, Bitmap favicon) {
              super.onPageStarted(view, url, favicon);
              String host=Uri.parse(url).getHost();
              if (!BuildConfig.IS_DEBUG) {
                  if (Arrays.binarySearch(domainList, host) < 0) {
                      //不在白名單內,非法網址,這個時候給用戶強烈而明顯的提示
                  } else {
                      //合法網址
                  }
              }
          }


          9.Android后臺無法釋放js導致發熱耗電

          原因:有些手機你如果webView加載的html里,有一些js一直在執行比如動畫之類的東西,如果此刻webView 掛在了后臺這些資源是不會被釋放用戶也無法感知。導致一直占有cpu 耗電特別快。

          解決方法:WebView在后臺的時候,會調用onStop方法,即此時關閉js交互,回到前臺調用onResume再開啟js交互。

           //在onResume里面設置setJavaScriptEnabled(true)。
              @Override
              protected void onResume() {
                  super.onResume();
                  if (mWebView !=null) {
                  mWebView.getSettings().setJavaScriptEnabled(true);
                  }
              }
          //在onStop里面設置setJavaScriptEnabled(false);
              @Override
              protected void onStop() {
                  super.onStop();
                  if (mWebView !=null) {
                  mWebView.getSettings().setJavaScriptEnabled(false)
                 }
            }


          10.WebView加載網頁不顯示圖片

          原因:WebView從Lollipop(5.0)開始webView默認不允許混合模式, https當中不能加載http資源, 而開發的時候可能使用的是https的鏈接,但是鏈接中的圖片可能是http的,所以顯示圖片失敗。

          解決方案:需要設置開啟。


          主站蜘蛛池模板: 黑人一区二区三区中文字幕| 一本岛一区在线观看不卡| 无码毛片一区二区三区中文字幕| 国产一区美女视频| 亚洲一区二区在线免费观看| 日本精品3d动漫一区二区| 精品乱码一区二区三区四区| 国产激情无码一区二区| 日韩人妻无码一区二区三区久久| 在线精品亚洲一区二区三区| 国产激情一区二区三区 | 国产精品一区三区| 精品亚洲一区二区| 国产一区二区三区影院| 国产成人欧美一区二区三区| 精品国产免费观看一区| 国产婷婷色一区二区三区深爱网 | 精品国产一区AV天美传媒| 国产精品视频一区二区三区| 日本v片免费一区二区三区| 国产一区二区三区在线免费观看| 国产一区在线播放| 中日av乱码一区二区三区乱码| 亚洲爆乳精品无码一区二区三区| 亚洲香蕉久久一区二区| 日韩AV在线不卡一区二区三区| 成人精品视频一区二区三区不卡| 青青青国产精品一区二区| 亚洲一区在线免费观看| 波多野结衣一区视频在线| av在线亚洲欧洲日产一区二区| 亚洲av日韩综合一区在线观看| 99精品国产一区二区三区2021| 鲁大师成人一区二区三区| 3d动漫精品啪啪一区二区中| 一级毛片完整版免费播放一区 | 国产精久久一区二区三区| 99精品国产高清一区二区麻豆| 一区二区三区www| 日韩免费无码一区二区视频| 精品一区二区三区在线播放视频|