WKWebView Cookie 的读取写入与同步

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

但是 WKWebview 有几个很坑的问题:

  1. Cache 与系统分开,并且在 iOS8上面无法清除(iOS9增加了相关方法).
  2. Cookie 与系统分开,web 的 cookie 与native 的 cookie 是分开的.
  3. 不走 NSURLProtocol,无法自定义网络请求.

So, 需要 native 与 web 统一 cookie 就无从谈起了,甚至 webview 于 webview 之间的 cookie 同步也有问题.

先来解决 webview 与 webview 之间的同步问题.

个 webview 页面里登录之后,另一个 webview 依旧是未登录的状态.

这个比较容易处理,让两个 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 这个条件达到的时候,会发生什么?我不确定.

再来解决自定义 Cookie 的问题

这个服务器一般有这样的需求,在 App 中 webview 发起请求,带一个特殊的 Cookie 字段来表示来源.

这个可以在合适的时候修改 NSRequest 来解决.

cookie 这个参数,是需要设置的 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 传进去.

这种方式实质是在发送给服务器的请求中伪造了 Cookie, 服务器在某些情况下回认的,但是, web 前端那边是肯定拿不到的这些 Cookie,当 web 前端发 ajax 请求的时候,更是不会带上这些自定义的 Cookie.

打通 web 前端与 native 之间的 cookie 存储.

似乎 WKProcesspool 创建的时候,会从 NSCookieStorage 里面读取 Cookie 之前看过一段 FireFox 的源码,他们是通过替换 WKProcesspool 来做到隐私浏览器的.

但是.....为什么叫 pool 呢?里面肯定有复用和缓存.

对一个已经存在的 WebView 替换 WKProcesspool 是不会立即生效的,即使替换了,也要过一段时间,等 WebView 持有的 process 失效,再次从 WKProcesspool 取 process 的时候才生效.然而,黄花菜已经凉了...

还有一种曲线救国的方法,就是用 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 依然是不同步的,服务器的登录状态无法保持.

网上所谓的 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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容