iOS WKWebView Cookie同步

  • 来源:新网
  • 更新日期:2018-03-21

摘要:摘要: iOS WKWebView Cookie同步

UIWebView简介

UIWebView从 iOS2 就有,iOS8 以后,苹果推出了新框架 WebKit,提供了替换 UIWebView 的组件 WKWebView。各种 UIWebView 的性能问题没有了,速度更快了,占用内存少了,体验更好了,下面列举一些其它的优势:

t01de1d90d53a307064.jpg
1、在性能、稳定性、功能方面有很大提升(加载速度,内存的提升谁用谁知道)
2、更多的支持 HTML5 的特性
3、官方宣称的高达60fps的滚动刷新率以及内置手势
4、Safari 相同的 JavaScript 引擎
5、将 UIWebViewDelegate 与 UIWebView 拆分成了14类与3个协议,包含该更细节功能的实现。
相比之下,WKWebView 复杂得多,一些常用API如下:

@protocol WKNavigationDelegate <NSObject> @optional //请求之前,决定是否要跳转:用户点击网页上的链接,需要打开新页面时,将先调用这个方法。 - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler; //接收到相应数据后,决定是否跳转 - (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler; //页面开始加载时调用 - (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(null_unspecified WKNavigation *)navigation; // 主机地址被重定向时调用 - (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(null_unspecified WKNavigation *)navigation; // 页面加载失败时调用 - (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(null_unspecified WKNavigation *)navigation withError:(NSError *)error; // 当内容开始返回时调用 - (void)webView:(WKWebView *)webView didCommitNavigation:(null_unspecified WKNavigation *)navigation; // 页面加载完毕时调用 - (void)webView:(WKWebView *)webView didFinishNavigation:(null_unspecified WKNavigation *)navigation; //跳转失败时调用 - (void)webView:(WKWebView *)webView didFailNavigation:(null_unspecified WKNavigation *)navigation withError:(NSError *)error; // 如果需要证书验证,与使用AFN进行HTTPS证书验证是一样的 - (void)webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *__nullable credential))completionHandler; //9.0才能使用,web内容处理中断时会触发 - (void)webViewWebContentProcessDidTerminate:(WKWebView *)webView NS_AVAILABLE(10_11, 9_0); @end
Cookie同步

不同于UIWebView,WKWebView会忽视默认的网络存储, NSURLCache, NSHTTPCookieStorage, NSCredentialStorage。 目前是这样的,WKWebView有自己的进程,同样也有自己的存储空间用来存储cookie和cache, 其他的网络类如NSURLConnection是无法访问到的。 同时WKWebView发起的资源请求也是不经过NSURLProtocol的,导致无法自定义请求。

方法1、同域名 C/S->B/S同步

如果C/S和B/S中,服务器端域名一致的话,在初始化WkWebView时同步即可

NSURL *url = [NSURL URLWithString:urlString]; NSMutableString *cookies = [NSMutableString string]; NSMutableURLRequest *requestObj = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10]; // 一般都只需要同步JSESSIONID,可视不同需求自己做更改 NSString * JSESSIONID; // 获取本地所有的Cookie NSArray *tmp = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies]; for (NSHTTPCookie * cookie in tmp) { if ([cookie.name isEqualToString:@"JSESSIONID"]) { JSESSIONID = cookie.value; break; } } if (JSESSIONID.length) { // 格式化Cookie [cookies appendFormat:@"JSESSIONID=%@;",JSESSIONID]; } // 注入Cookie [requestObj setValue:cookies forHTTPHeaderField:@"Cookie"]; // 加载请求 [self.wk_webView loadRequest:requestObj];

 

方法2、不同域名C/S->B/S


注意:我们这里实际上重新loadRequest了,正常情况下,我们应该拷贝原来的request

NSMutableURLRequest*mutableRequest=[requestmutableCopy];//拷贝request

方法三3、B/S->C/S同步

在WkWebView接收到Response后,将Response带的Cookies取出,然后直接放入[NSHTTPCookieStorage sharedHTTPCookieStorage] 容器中:

- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler{ NSHTTPURLResponse *response = (NSHTTPURLResponse *)navigationResponse.response; NSArray *cookies =[NSHTTPCookie cookiesWithResponseHeaderFields:[response allHeaderFields] forURL:response.URL]; for (NSHTTPCookie *cookie in cookies) { [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:cookie]; } decisionHandler(WKNavigationResponsePolicyAllow); }

 

方法评价

所有的同步过程中,我们发现使用了NSHTTPCookieStorage(当然UIWebView也使用了此类自动同步),对于方法1而言,对于跳转则会丢失cookie,因此实际使用中推荐2、3两种方法。

 

注意:方法2给出的是个简单例子,由于不同域名同步时,我们获取到cookie种Domain和Path可能不同,否则,因此需要手动替换,否则同样无法同步。