前因
WKWebView有自己的进程,独立于iOS App的进程,使用自己的存储空间来存储cookie和cache,WKWebView会忽视NSURLCache、NSHTTPCookieStorage、NSCredentialStorage这些默认的网络存储。 WKWebView 发起的请求不会自动带上存储于 NSHTTPCookieStorage 容器中的 Cookie。
所以我们需要自己注入cookie到WKWebView中
iOS 11以后
苹果提供了WKHTTPCookieStore处理WKWebView的cookie,我们将NSHTTPCookieStorage里面的cookie取出后设置到WKHTTPCookieStore中就可以了,代码示例
1 2 3 4
| NSArray *cookieArr = [NSHTTPCookieStorage sharedHTTPCookieStorage].cookies; [cookieArr enumerateObjectsUsingBlock:^(NSHTTPCookie * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { [self.webView.configuration.websiteDataStore.httpCookieStore setCookie:obj completionHandler:nil]; }];
|
iOS 11以前
WKWebView中cookie的解决方案有:
方案1:WKWebView loadRequest 前,在 request header 中设置 Cookie, 解决首个请求 Cookie 带不上的问题;
缺陷:只能解决指定的一个URL的请求,涉及到同域的Ajax跳转还是会缺失cookie
方案2: 通过 document.cookie 设置 Cookie 解决后续页面(同域)Ajax、iframe 请求的 Cookie 问题;
缺陷:不能解决跨域cookie的问题
方案3:每次页面跳转的时候回调用decidePolicyForNavigationAction回调,那么就可以在回调里拦截请求,加入cookie后重新发送。
缺陷:loadRequest是加载mainFrame请求,所以依然解决不了页面 iframe 跨域请求的 Cookie 问题
由于暂时没有遇到跨域请求cookie的问题,所以这里就不讨论方案3了。
代码示例:
1 2 3 4 5 6 7 8 9 10 11 12
| NSArray *cookieArr = [NSHTTPCookieStorage sharedHTTPCookieStorage].cookies; NSMutableString *str = [NSMutableString new]; for (NSHTTPCookie *ck in cookieArr) { if ([ck.domain containsString:@".taobao.com"]) { [str appendFormat:@"document.cookie = '%@=%@;domain=.taobao.com;path=/';\n", ck.name, ck.value]; } } // 方案1 request.allHTTPHeaderFields = [NSHTTPCookie requestHeaderFieldsWithCookies:cookieArr]; // 方案2 WKUserScript *script = [[WKUserScript alloc] initWithSource:str injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO]; [self.webView.configuration.userContentController addUserScript:script];
|
方案2中,需要注意多cookie注入时,注入的字符串是以下格式,有多个 document.cookie
标志,而不是只有一个
1 2 3 4 5
| document.cookie = 'RCRM_CODCS_WELOG_ID=B2VTGSYJHKKKECM8ITC0F95JFD70OD19420211012105246833;domain=.taobao.com;path=/' document.cookie = 'symmetricKey=false;domain=.taobao.com;path=/' document.cookie = 'taobaoToken=0AB9696085D923A8345E009504580D0B8694890CC2029A4D52EB5F63FB4F8AC9B61654474;domain=.taobao.com;path=/' document.cookie = 'userId=ozf_BuHlDefVjJwSuEQ5xxGL7ZvI;domain=.taobao.com;path=/' document.cookie = 'userIdType=2;domain=.taobao.com;path=/'
|
调试
通过iPhone连接Mac电脑,使用Safari的开发工具可以调试手机的H5页面,可以验证cookie是否注入成功。如下图,cookie成功注入
参考