WKWebView 设置 Cookie

在 Apple 推出 WKWebView 之后,大家都知道 WKWebView 比 UIWebView 更加优秀,WKWebView 确实是优秀,但是也存在一些问题,比如被人诟病的 cookie 设置问题。

在使用 UIWebView 的时候,我们是通过 NSHTTPCookieStorage 来管理 cookie 的,我们给 mobi.domain.com 域名添加一个名字为 auth 的 cookie,代码类似下面。

NSMutableDictionary *cookieProperties = [NSMutableDictionary dictionary];
[cookieProperties setObject:@"auth" forKey:NSHTTPCookieName];
[cookieProperties setObject:@"xxxxxx" forKey:NSHTTPCookieValue];
[cookieProperties setObject:@"mobi.domain.com" forKey:NSHTTPCookieDomain];
[cookieProperties setObject:@"/" forKey:NSHTTPCookiePath];
NSHTTPCookie *cookie = [NSHTTPCookie cookieWithProperties:cookieProperties];
[[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:cookie];

在 WKWebView 中通过 NSHTTPCookieStorage 来设置 cookie 是行不通的,要通过 URLRequest 来添加 cookie 才能起效果 。代码类似下面。

NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:@"http://mobi.domain.com"]];
NSDictionary *headFields = request.allHTTPHeaderFields;
NSString *    cookie = headFields[@"auth"];
if (cookie == nil) {
      [request addValue:[NSString stringWithFormat:@"auth=%@", @"authValue"] forHTTPHeaderField:@"Cookie"];
    }
[self.webView loadRequest:request];

你以为 WKWebView 添加 cookie 就这样结束了 ? 其实远远没有。上面通过 URLRequest 来添加 cookie 的方式只能对 WKWebView loadRequest 的那个 request 起作用,如果你的 WKWebView 加载的 Web 页面包含了 ajax 请求的话,那 cookie 又要重新处理了,这个处理需要在 WKWebView 的 WKWebViewConfiguration 中进行配置。代码类似下面。

    //应用于 ajax 请求的 cookie 设置
    WKUserContentController *userContentController = WKUserContentController.new;
    NSString *cookieSource = [NSString stringWithFormat:@"document.cookie = 'auth=%@';", @"authValue"];
    WKUserScript *cookieScript = [[WKUserScript alloc] initWithSource:cookieSource injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO];
    [userContentController addUserScript:cookieScript];
    WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
    config.userContentController = userContentController;
    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:@"http://mobi.domain.com"]];
    
   // 应用于 request 的 cookie 设置
    NSDictionary *headFields = request.allHTTPHeaderFields;
    NSString *    cookie = headFields[@"auth"];
    if (cookie == nil) {
        [request addValue:[NSString stringWithFormat:@"auth=%@", @"authValue"] forHTTPHeaderField:@"Cookie"];
    }

    self.webView = [[WKWebView alloc] initWithFrame:self.view.frame configuration:config];
    [self.webView loadRequest:request];

到这里是不是结束了呢?其实还是没有,从这篇文章 《 WKWebView 那些坑》(https://mp.weixin.qq.com/s/rhYKLIbXOsUJC_n6dt9UfA)中可以看到 “ document.cookie()无法跨域设置 cookie ”,显然如果你的 WKWebView 页面没有跨域问题的话,那么通过以上的方式是可以解决 WKWebView 设置 cookie 的问题。

到最后献上苹果工程师在官方论坛的一个关于 WKWebView Cookie 问题的答复 (https://forums.developer.apple.com/thread/77279),该答复大意是说,如果要保证 cookie 正常工作,那么就不要使用 WKWebView,而是使用 UIWebView 。如果你在考虑是否从 UIWebView 迁移到 WKWebView 的话,建议你先看看 《 WKWebView 那些坑》(https://mp.weixin.qq.com/s/rhYKLIbXOsUJC_n6dt9UfA),如果你的业务无法规避或者处理里面提到的一些 WKWebView 巨坑,那么我认为 WKWebView 对你来说并不是一个更好的选择。

参考

  1. https://mp.weixin.qq.com/s/rhYKLIbXOsUJC_n6dt9UfA
  2. https://forums.developer.apple.com/thread/77279
  3. https://stackoverflow.com/questions/26573137/can-i-set-the-cookies-to-be-used-by-a-wkwebview/26577303#26577303

推荐阅读更多精彩内容

  • 首先是UIWebView的设置cookie 删除cookie UIWebView向上面那样设置就可以设置好cook...
    yuandiLiao阅读 981评论 0 0
  • WKWebView本来是有设置cookie的api的,具体做法如下 结果如何呢?等网页加载出来后,在web检查器中...
    广锅锅阅读 1,882评论 7 2
  • 问题情境:首先要找到cookie,那么针对登录认证后的一种状态,如何通过设置HTTP 的header来访问一个H5...
    贾代表阅读 213评论 0 3
  • 前言 关于UIWebView的介绍,相信看过上文的小伙伴们,已经大概清楚了吧,如果有问题,欢迎提问。 本文是本系列...
    CoderLF阅读 5,194评论 2 7
  • WKWebView 是苹果在 WWDC 2014 上推出的新一代 webView 组件,用以替代 UIKit 中笨...
    Aiana阅读 2,484评论 1 6