WKWebView之cookie的同步与管理

WKWebView之cookie的同步与管理

一、引言

     iOS 11.0 之前,WKWebView 对于NSHTTPCookieStorage 的 Cookie 并不会每次都携带,对cookie管理一直是它的短板。iOS 11.0 推出WKHTTPCookieStore之后,WKWebView 对cookie 的管理改善了很多。基于H5对cookie的业务以来比较多。下文将介绍WKWebView cookie 管理。


二、iOS 11.0 之前cookie 捕获与注入

1. 捕获cookie

     由于实现拦截协议时,WKNavigationDelegate 代理方法会失效,暂时不清楚什么原因,知道的伙伴告诉一下。以下是在 WKWebView的代理方法。

  • WKNavigationDelegate捕获访问网站的cookie信息

- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler
{
     //存储cookies
     dispatch_sync(dispatch_get_global_queue(0, 0), ^{
            NSHTTPURLResponse *response = (NSHTTPURLResponse *)navigationResponse.response;
            NSArray *cookies =[NSHTTPCookie cookiesWithResponseHeaderFields:[response allHeaderFields] forURL:response.URL];
    }
    decisionHandler(WKNavigationResponsePolicyAllow);
}

2.NSURLRequest注入cookie

   由于业务需求,WKWebView需要依赖cookie作登录状态校验,但是WKWebView并不依赖于NSHTTPCookieStorage。后来发现通过NSURLRequest注入cookie的方法可以有效解决该问题,但是通过NSURLRequest注入的方法依然无法使cookie长期有效。以下为通过NSURLRequest 注入cookie的方法。

   注入cookie时我们需要兼容加载php和js两种形式(注意:插入cookie时必须在请求之前)。

  • PHP携带cookie的形式
 //通过host关联cookie。
 [request setValue: [cookieSting appendString:
 [NSString stringWithFormat:@"%@ = %@;",cookie.name,cookie.value]] 
 forHTTPHeaderField:@"Cookie"];

  • JS携带cookie的形式

//关联cookie时host 关联。  
WKUserScript * cookieScript = [[WKUserScript alloc] initWithSource: 
[NSString stringWithFormat:@"document.cookie = '%@=%@';",cookie.name,cookie.value] 
injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO];
[self.config.userContentController addUserScript: cookieScript];


三、iOS 11.0 cookie获取和插入

   iOS11.0推出WKHTTPCookieStore后,cookie的管理将变得非常简单。WKHTTPCookieStore的使用和原理类似于NSHTTPCookieStorage;它将访问时获取的cookies自动存储在本地,下次访问时将自动携带相对应的cookie。

1. 获取cookie


//WKHTTPCookieStore的使用 
WKHTTPCookieStore *cookieStore = self.webView.configuration.websiteDataStore.httpCookieStore;
//get cookies
[cookieStore getAllCookies:^(NSArray<NSHTTPCookie *> * _Nonnull cookies) {
      NSLog(@"All cookies %@",cookies);
}];

2.注入cookie


//发送请求前插入cookie;
WKHTTPCookieStore *cookieStore = self.webiew.configuration.websiteDataStore.httpCookieStore;
[cookieStore setCookie:cookie completionHandler:nil];


四、cookie本地化管理

   解决和cookie的捕获和插入的问题,那么cookie的本地化管理以及与NSHTTPCookieStorage 的cookie同步就迎刃而解了。

cookie本地化管理方案


cookie管理

方案解决的问题
  • 兼容 iOS 11.0;
  • NSHTTPCookieStorage 、WKHTTPCookieStore与本地磁盘cookies 的同步;
  • 本地磁盘的管理;
  • cookies的捕获和注入;

1. cookie的插入


- (void)insertCookie:(NSHTTPCookie *)cookie
{
    @autoreleasepool {

        if (@available(iOS 11.0, *)) {
            WKHTTPCookieStore *cookieStore = self.configuration.websiteDataStore.httpCookieStore;
            [cookieStore setCookie:cookie completionHandler:nil];
            return;
        }

        NSMutableArray *TempCookies = [NSMutableArray array];
        NSMutableArray *localCookies =[NSKeyedUnarchiver unarchiveObjectWithData:[[NSUserDefaults standardUserDefaults] objectForKey: PAWKCookiesKey]];
        for (int i = 0; i < localCookies.count; i++) {
            NSHTTPCookie *TempCookie = [localCookies objectAtIndex:i];
            if ([cookie.name isEqualToString:TempCookie.name]) {
                [localCookies removeObject:TempCookie];
                i--;
                break;
            }
        }
        [TempCookies addObjectsFromArray:localCookies];
        [TempCookies addObject:cookie];
        NSData *cookiesData = [NSKeyedArchiver archivedDataWithRootObject: TempCookies];
        [[NSUserDefaults standardUserDefaults] setObject:cookiesData forKey:PAWKCookiesKey];
        [[NSUserDefaults standardUserDefaults] synchronize];
     }
}

2.NSHTTPCookieStorage 和本地磁盘cookie的同步


- (NSMutableArray *)sharedHTTPCookieStorage
{
    @autoreleasepool {
        NSMutableArray *cookiesArr = [NSMutableArray array];
        /** 获取NSHTTPCookieStorage cookies */
        NSHTTPCookieStorage * shareCookie = [NSHTTPCookieStorage sharedHTTPCookieStorage];
        for (NSHTTPCookie *cookie in shareCookie.cookies){
            [cookiesArr addObject:cookie];
        }

        /** 获取自定义存储的cookies */
        NSMutableArray *cookies = [NSKeyedUnarchiver unarchiveObjectWithData: [[NSUserDefaults standardUserDefaults] objectForKey: PAWKCookiesKey]];

        //清除过期的cookies
        for (int i = 0; i < cookies.count; i++) {
            NSHTTPCookie *cookie = [cookies objectAtIndex:i];
            if (!cookie.expiresDate) {
                continue;
            }
            if ([cookie.expiresDate compare:self.currentTime]) {
                [cookiesArr addObject:cookie];
            }else
            {
                [cookies removeObject:cookie];
                i--;
            }
        }
        //存储最新的cookies
        NSData *cookiesData = [NSKeyedArchiver archivedDataWithRootObject: cookies];
        [[NSUserDefaults standardUserDefaults] setObject:cookiesData forKey:PAWKCookiesKey];
        [[NSUserDefaults standardUserDefaults] synchronize];

        return cookiesArr;
    }
}

3.WKHTTPCookieStore Cookie同步


- (void)syncCookiesToWKHTTPCookieStore:(WKHTTPCookieStore *)cookieStore API_AVAILABLE(macosx(10.13), ios(11.0))
{
     NSMutableArray *cookieArr = [self sharedHTTPCookieStorage];
     if (cookieArr.count == 0)return;
     for (NSHTTPCookie *cookie in cookieArr) {
        [cookieStore setCookie:cookie completionHandler:nil];
     }
}

4.清除Cookie


- (void)deleteAllWKCookies
{
    if (@available(iOS 11.0, *)) {
        NSSet *websiteDataTypes = [NSSet setWithObject:WKWebsiteDataTypeCookies];
        NSDate *dateFrom = [NSDate dateWithTimeIntervalSince1970:0];
        [[WKWebsiteDataStore defaultDataStore] removeDataOfTypes:websiteDataTypes modifiedSince:dateFrom completionHandler:nil];
    }

    NSData *cookiesData = [NSKeyedArchiver archivedDataWithRootObject: @[]];
    [[NSUserDefaults standardUserDefaults] setObject:cookiesData forKey:PAWKCookiesKey];
    [[NSUserDefaults standardUserDefaults] synchronize];
}

五、使用

   使用详情请看PAWebViewgithub:https://github.com/llyouss/PAWeView

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值