WKWebView get/set cookie小结

###1、同步cookie 工具类

@interface WKCookieSyncManager : NSObject

@property (nonatomic, strong) WKProcessPool *processPool;
@property (nonatomic, assign) BOOL loginCookieHasBeenSynced;

+ (instancetype)sharedWKCookieSyncManager;

+ (NSMutableArray<NSString *> *)cookieJavaScriptArray;

- (void)setCookies:(NSArray<NSHTTPCookie *> *)cookies forDomain:(NSString *)domain;

- (NSArray<NSHTTPCookie *> *)cookies;

- (void)removeCookies;

- (void)cookiesSyncForWebsiteDataStore:(void(^)(WKWebsiteDataStore *dataStore))completion;

+ (void)syncCookieFromWebView:(WKWebView *)webView navigationResponse:(WKNavigationResponse *)navigationResponse;

@end
复制代码

WKCookieSyncManager implementation

@interface WKCookieSyncManager () <WKNavigationDelegate>

@property (nonatomic, copy) NSString *domain;
@property (nonatomic, strong) dispatch_group_t cookieSyncGroup;

@end

@implementation WKCookieSyncManager

+ (instancetype)sharedWKCookieSyncManager {
    static WKCookieSyncManager *sharedWKCookieSyncManagerInstance = nil;
    static dispatch_once_t predicate;
    dispatch_once(&predicate, ^{
        sharedWKCookieSyncManagerInstance = [[self alloc] init];
    });
    return sharedWKCookieSyncManagerInstance;
}

- (WKProcessPool *)processPool {
    if (!_processPool) {
        static dispatch_once_t predicate;
        dispatch_once(&predicate, ^{
            _processPool = [[WKProcessPool alloc] init];
        });
    }
    return _processPool;
}

- (instancetype)init {
    self = [super init];
    if (self) {
        _domain = @"your domain";
        _cookieSyncGroup = dispatch_group_create();
    }
    return self;
}

+ (NSMutableArray<NSString *> *)cookieJavaScriptArray {
    NSMutableArray<NSString *> *cookieStrings = [[NSMutableArray alloc] init];
    NSArray *cookies = [[WKCookieSyncManager sharedWKCookieSyncManager] cookies];
    for (NSHTTPCookie *cookie in cookies) {
        NSString *excuteJSString = [NSString stringWithFormat:@"%@=%@;", cookie.name, cookie.value];
        if (cookie.domain.length > 0) {
            excuteJSString = [excuteJSString stringByAppendingFormat:@"domain=%@;", cookie.domain];
        }
        if (cookie.path.length > 0) {
            excuteJSString = [excuteJSString stringByAppendingFormat:@"path=%@;", cookie.path];
        }
        if (cookie.expiresDate != nil) {
            excuteJSString = [excuteJSString stringByAppendingFormat:@"expires=%@;", cookie.expiresDate];
        }
        if (cookie.secure) {
            excuteJSString = [excuteJSString stringByAppendingString:@"secure=true"];
        }
        
        [cookieStrings addObject:excuteJSString];
        NSLog(@"cookie to be set = %@", excuteJSString);
    }
    // 检查cookie的数量,正常的应该是 7 个
    NSLog(@"cookieJavaScriptArray.cookie.length = %ld", cookieStrings.count);
    
    return cookieStrings;
}

- (void)setCookies:(NSArray<NSHTTPCookie *> *)cookies forDomain:(NSString *)domain {
    if (![domain containsString:self.domain]) {
        return;
    }
    NSData *cookieData = [NSKeyedArchiver archivedDataWithRootObject:cookies];
    [[NSUserDefaults standardUserDefaults] setObject:cookieData forKey:self.domain];
    [[NSUserDefaults standardUserDefaults] synchronize];
    
    self.loginCookieHasBeenSynced = YES;
}

- (NSArray<NSHTTPCookie *> *)cookies {
    NSData *cookieData = [[NSUserDefaults standardUserDefaults] objectForKey:self.domain];
    if (!cookieData) {
        return nil;
    }
    
    NSArray *cookies = [NSKeyedUnarchiver unarchiveObjectWithData:cookieData];
    for (NSHTTPCookie *cookie in cookies) {
        NSLog(@"cookie== %@",cookie);
    }
    return cookies;
}

- (void)removeCookies {
    [[NSUserDefaults standardUserDefaults] removeObjectForKey:self.domain];
    [[NSUserDefaults standardUserDefaults] synchronize];
    self.loginCookieHasBeenSynced = NO;
}

- (void)cookiesSyncForWebsiteDataStore:(void(^)(WKWebsiteDataStore *dataStore))completion {
    NSArray<NSHTTPCookie *> *cookes = [self cookies];
    if (!cookes || cookes.count == 0) {
        return completion(nil);
    }
    
    if (@available(iOS 11.0, *)) {
        WKWebsiteDataStore *dataStore = [WKWebsiteDataStore nonPersistentDataStore];
        
        [cookes enumerateObjectsUsingBlock:^(NSHTTPCookie *cookie, NSUInteger idx, BOOL *stop) {
            NSLog(@"cookie == %@", cookie);
            dispatch_group_enter(self.cookieSyncGroup);
            
            [dataStore.httpCookieStore setCookie:cookie completionHandler:^{
                dispatch_group_leave(self.cookieSyncGroup);
            }];
        }];
        
        dispatch_group_notify(self.cookieSyncGroup, dispatch_get_main_queue(), ^{
            completion(dataStore);
        });
        return;
    }
    
    completion(nil);
}

+ (void)syncCookieFromWebView:(WKWebView *)webView
           navigationResponse:(WKNavigationResponse *)navigationResponse {
    
    if (@available(iOS 11.0, *)) {
        WKHTTPCookieStore *cookieStore = webView.configuration.websiteDataStore.httpCookieStore;
        [cookieStore getAllCookies:^(NSArray* cookies) {
            if (cookies.count == 0) {
                return ;
            }

            NSUInteger index = [cookies indexOfObjectPassingTest:^BOOL(NSHTTPCookie *cookie, NSUInteger idx, BOOL * _Nonnull stop) {
                return [cookie.name isEqualToString:[WKCookieSyncManager sharedWKCookieSyncManager].domain];
            }];

            if (index == NSNotFound) {
                return;
            }

            NSHTTPURLResponse *response = (NSHTTPURLResponse *)navigationResponse.response;
            NSString *host = response.URL.host;
            if (![[WKCookieSyncManager sharedWKCookieSyncManager] loginCookieHasBeenSynced]) {
                [[WKCookieSyncManager sharedWKCookieSyncManager] setCookies:cookies forDomain:host];
            }
        }];
        return;
    }
    
    NSHTTPURLResponse *response = (NSHTTPURLResponse *)navigationResponse.response;
    NSDictionary *allHeaderFields = [response allHeaderFields];
    
    NSString *cookiesString = [allHeaderFields valueForKey:@"Set-Cookie"];
    NSLog(@"response.URL Set-Cookie:%@", cookiesString);
    
    NSArray *cookies = [NSHTTPCookie cookiesWithResponseHeaderFields:allHeaderFields forURL:response.URL];
    
    NSUInteger index = [cookies indexOfObjectPassingTest:^BOOL(NSHTTPCookie *cookie, NSUInteger idx, BOOL * _Nonnull stop) {
        return [cookie.name isEqualToString:[WKCookieSyncManager sharedWKCookieSyncManager].domain];
    }];
    
    if (index != NSNotFound) {
        NSString *host = response.URL.host;
        if (![[WKCookieSyncManager sharedWKCookieSyncManager] loginCookieHasBeenSynced]) {
            [[WKCookieSyncManager sharedWKCookieSyncManager] setCookies:cookies forDomain:host];
        }
    }
}

@end
复制代码

###2、通过- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler获取WKWebView cookies ,使用工具类保存起来

- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler {

    dispatch_async(dispatch_get_main_queue(), ^{
       [WKCookieSyncManager syncCookieFromWebView:webView navigationResponse:navigationResponse];
    });
    
    decisionHandler(WKNavigationResponsePolicyAllow);
}
复制代码

3、首次打开应用,初始化WKWebView 设置已保存的Cookies,同步cookie登录态

    WKCookieSyncManager *cookiesManager = [WKCookieSyncManager sharedWKCookieSyncManager];
    WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
    // 解决 webview之间的cookie同步问题,
    config.processPool = cookiesManager.processPool; 
    config.allowsInlineMediaPlayback = YES;
    
    if (@available(iOS 11.0, *)) {
            NSArray<NSHTTPCookie *> *cookes = [[WKCookieSyncManager sharedWKCookieSyncManager] cookies];
            [cookes enumerateObjectsUsingBlock:^(NSHTTPCookie *cookie, NSUInteger idx, BOOL * _Nonnull stop) {
                [config.websiteDataStore.httpCookieStore setCookie:cookie completionHandler:nil];
            }];
        } else {
            NSMutableArray<NSString *> *oldCookies = [WKCookieSyncManager cookieJavaScriptArray];
            [oldCookies enumerateObjectsUsingBlock:^(NSString *_Nonnull obj, NSUInteger idx, BOOL *_Nonnull stop) {
                NSString *setCookie = [NSString stringWithFormat:@"document.cookie='%@';", obj];
                WKUserScript *cookieScript = [[WKUserScript alloc] initWithSource:setCookie injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:YES];
                [config.userContentController addUserScript:cookieScript];
            }];
        }
    
    WKWebView *webView = [[WKWebView alloc] initWithFrame:self.view.bounds configuration:config];
    self.webView = webView;
    self.webView.backgroundColor = [UIColor whiteColor];
    self.webView.scrollView.backgroundColor = [UIColor whiteColor];
    self.webView.translatesAutoresizingMaskIntoConstraints = NO;
    self.webView.scrollView.bounces = NO;
    self.webView.UIDelegate = self;
    [self.view addSubview:self.webView];
复制代码

###4、- (void)webView:(WKWebView *)webView didFinishNavigation:(null_unspecified WKNavigation *)navigation 获取cookie string

- (void)webView:(WKWebView *)webView didFinishNavigation:(null_unspecified WKNavigation *)navigation {
    [self.webView evaluateJavaScript:@"document.cookie" completionHandler:^(id _Nullable cookie, NSError * _Nullable error) {
            NSLog(@"调用异步获取cookie:%@", cookie);
        }];
}
复制代码

转载于:https://juejin.im/post/5bc692ef5188255c89015cf5

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值