WKWebView Cookie 的讀取寫入與同步

iOS8 以后推出了 WKWebview,顯示更快效率更高.

但是 WKWebview 有幾個很坑的問題:

  1. Cache 與系統(tǒng)分開,并且在 iOS8上面無法清除(iOS9增加了相關方法).
  2. Cookie 與系統(tǒng)分開,web 的 cookie 與native 的 cookie 是分開的.
  3. 不走 NSURLProtocol,無法自定義網(wǎng)絡請求.

So, 需要 native 與 web 統(tǒng)一 cookie 就無從談起了,甚至 webview 于 webview 之間的 cookie 同步也有問題.

先來解決 webview 與 webview 之間的同步問題.

個 webview 頁面里登錄之后,另一個 webview 依舊是未登錄的狀態(tài).

這個比較容易處理,讓兩個 webview 使用同一個 WKProcesspool 就可以了.

self.sharedProcessPool = [[WKProcessPool alloc]init];
webViewConfiguration = [[WKWebViewConfiguration alloc] init];
WKUserContentController *contentController = [[WKUserContentController alloc] init];
webViewConfiguration.userContentController = contentController;
webViewConfiguration.processPool = self.sharedProcessPool;

上面代碼里,WKProcesspool 簡單寫了一下.實際使用的時候,需要把 sharedProcessPool 做成單例模式,每一個需要同步的 WKWebview 都設置這個 processPool.

但是,注意官方文檔有這樣的描述:
The process pool associated with a web view is specified by its web view configuration. Each web view is given its own Web Content process until an implementation-defined process limit is reached; after that, web views with the same process pool end up sharing Web Content processes.

implementation-defined process limit is reached 這個條件達到的時候,會發(fā)生什么?我不確定.

再來解決自定義 Cookie 的問題

這個服務器一般有這樣的需求,在 App 中 webview 發(fā)起請求,帶一個特殊的 Cookie 字段來表示來源.

這個可以在合適的時候修改 NSRequest 來解決.

cookie 這個參數(shù),是需要設置的 Cookie 字符串,形式是類似:key1=val1;key2=val2這樣子的.每一個 key val 對,對應著一個NSHttpCookie 對象.

- (void) webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler{
    
    
if ([navigationAction.request allHTTPHeaderFields][@"Cookie"] && [[navigationAction.request allHTTPHeaderFields][@"Cookie"] rangeOfString:cookie].length > 0) {
        decisionHandler(WKNavigationActionPolicyAllow);
    }else{
        NSMutableURLRequest *request= [NSMutableURLRequest requestWithURL:url];
        [request setValue:cookie forHTTPHeaderField:@"Cookie"];
        [webView loadRequest:request];
         decisionHandler(WKNavigationActionPolicyCancel);
    }

}

可以在這里把 NSCookieStorage 里的 native 存儲的 cookie 傳進去.

這種方式實質是在發(fā)送給服務器的請求中偽造了 Cookie, 服務器在某些情況下回認的,但是, web 前端那邊是肯定拿不到的這些 Cookie,當 web 前端發(fā) ajax 請求的時候,更是不會帶上這些自定義的 Cookie.

打通 web 前端與 native 之間的 cookie 存儲.

似乎 WKProcesspool 創(chuàng)建的時候,會從 NSCookieStorage 里面讀取 Cookie 之前看過一段 FireFox 的源碼,他們是通過替換 WKProcesspool 來做到隱私瀏覽器的.

但是.....為什么叫 pool 呢?里面肯定有復用和緩存.

對一個已經(jīng)存在的 WebView 替換 WKProcesspool 是不會立即生效的,即使替換了,也要過一段時間,等 WebView 持有的 process 失效,再次從 WKProcesspool 取 process 的時候才生效.然而,黃花菜已經(jīng)涼了...

還有一種曲線救國的方法,就是用 JS 來做 cookie 的讀取與存儲.

KUserContentController* userContentController = WKUserContentController.new;  
WKUserScript * cookieScript = [[WKUserScript alloc]   
    initWithSource: @"document.cookie = 'TeskCookieKey1=TeskCookieValue1';document.cookie = 'TeskCookieKey2=TeskCookieValue2';"  
    injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO];  
// again, use stringWithFormat: in the above line to inject your values programmatically  
[userContentController addUserScript:cookieScript];  
WKWebViewConfiguration* webViewConfig = WKWebViewConfiguration.new;  
webViewConfig.userContentController = userContentController;  
WKWebView * webView = [[WKWebView alloc] initWithFrame:CGRectMake(/*set your values*/) 

只有部分無關痛癢的 cookie 能存取.用處并不大.

至關重要的 sessionid 這個 cookie, 早已被服務器設置了 HttpOnly 屬性!然后被 WebView 保護起來,不允許通過前端的方式修改.

想要修改sessionid, 只能從 WebView 提供的接口入手,但是, WKwebview 沒有這樣的接口.

所以, native 與 web 的 sessionid 依然是不同步的,服務器的登錄狀態(tài)無法保持.

網(wǎng)上所謂的 UIWebView WKWebView 和 Native 之間同步 Cookie 的方法,只要看到里面有 Javascript 代碼的,都存在這個問題,根本原因就在于HTML 頁面是不能通過 Javascript 代碼來修改 HttpOnly 屬性是 true 的 Cookie .

相信沒有哪個后臺會冒著 sessionid 被冒用的風險,把 sessionid 屬性的 HttpOnly 設置成 false.

最后,還是換回 UIWebView 吧!

http://stackoverflow.com/questions/25797972/cookie-sharing-between-multiple-wkwebviews
http://stackoverflow.com/questions/27043103/losing-cookies-in-wkwebview

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容