WKWebview注入Cookie和刪除Cookie

最近研究了一下給webview注入Cookie,主要針對的是WKWebview,畢竟UIWebview到年底蘋果就不再支持了。而且針對WKWebview,蘋果在iOS11之后新出了類WKHTTPCookieStore 以及對應(yīng)的API來操作Cookie。

一、Cookie的生成

首先看下生成Cookie的類 NSHTTPCookie,打開源碼可以看到要生成Cookie所對應(yīng)的key值,里面包括:name、value、url、版本、域名、過期日期等等key值,如下:

FOUNDATION_EXPORT NSHTTPCookiePropertyKey const NSHTTPCookieName;
FOUNDATION_EXPORT NSHTTPCookiePropertyKey const NSHTTPCookieValue;
FOUNDATION_EXPORT NSHTTPCookiePropertyKey const NSHTTPCookieOriginURL;
FOUNDATION_EXPORT NSHTTPCookiePropertyKey const NSHTTPCookieVersion;
FOUNDATION_EXPORT NSHTTPCookiePropertyKey const NSHTTPCookieDomain;
FOUNDATION_EXPORT NSHTTPCookiePropertyKey const NSHTTPCookiePath;
FOUNDATION_EXPORT NSHTTPCookiePropertyKey const NSHTTPCookieSecure;
FOUNDATION_EXPORT NSHTTPCookiePropertyKey const NSHTTPCookieExpires;
FOUNDATION_EXPORT NSHTTPCookiePropertyKey const NSHTTPCookieComment;
FOUNDATION_EXPORT NSHTTPCookiePropertyKey const NSHTTPCookieCommentURL;
FOUNDATION_EXPORT NSHTTPCookiePropertyKey const NSHTTPCookieDiscard;
FOUNDATION_EXPORT NSHTTPCookiePropertyKey const NSHTTPCookieMaximumAge;
FOUNDATION_EXPORT NSHTTPCookiePropertyKey const NSHTTPCookiePort;
FOUNDATION_EXPORT NSHTTPCookiePropertyKey const NSHTTPCookieSameSitePolicy API_AVAILABLE(macos(10.15), ios(13.0), watchos(6.0), tvos(13.0));
FOUNDATION_EXPORT NSHTTPCookieStringPolicy const NSHTTPCookieSameSiteLax API_AVAILABLE(macos(10.15), ios(13.0), watchos(6.0), tvos(13.0));
FOUNDATION_EXPORT NSHTTPCookieStringPolicy const NSHTTPCookieSameSiteStrict API_AVAILABLE(macos(10.15), ios(13.0), watchos(6.0), tvos(13.0));

還有可以直接獲取Cookie的一些屬性,不過都是只讀的,如下:

@property (nullable, readonly, copy) NSDictionary<NSHTTPCookiePropertyKey, id> *properties;
@property (readonly) NSUInteger version;
@property (readonly, copy) NSString *name;
@property (readonly, copy) NSString *value;
@property (nullable, readonly, copy) NSDate *expiresDate;
@property (readonly, getter=isSessionOnly) BOOL sessionOnly;
@property (readonly, copy) NSString *domain;
@property (readonly, copy) NSString *path;
@property (readonly, getter=isSecure) BOOL secure;
@property (readonly, getter=isHTTPOnly) BOOL HTTPOnly;
@property (nullable, readonly, copy) NSString *comment;
@property (nullable, readonly, copy) NSURL *commentURL;
@property (nullable, readonly, copy) NSArray<NSNumber *> *portList;
@property (nullable, readonly, copy) NSHTTPCookieStringPolicy sameSitePolicy API_AVAILABLE(macos(10.15), ios(13.0), watchos(6.0), tvos(13.0));

下面是生成Cookie的一些方法:

- (nullable instancetype)initWithProperties:(NSDictionary<NSHTTPCookiePropertyKey, id> *)properties;
+ (nullable NSHTTPCookie *)cookieWithProperties:(NSDictionary<NSHTTPCookiePropertyKey, id> *)properties;

其中 properties 就是一個字典,用來設(shè)置生成Cookie的一些鍵值對。
所以可以用以下方式來生成Cookie:

NSMutableDictionary *cookieProperties = [NSMutableDictionary dictionary];
[cookieProperties setObject:@"name" forKey:NSHTTPCookieName];
[cookieProperties setObject:@"value" forKey:NSHTTPCookieValue];
[cookieProperties setObject:@"jianshu.com" forKey:NSHTTPCookieDomain];
[cookieProperties setObject:@"jianshu.com" forKey:NSHTTPCookieOriginURL];
[cookieProperties setObject:@"/" forKey:NSHTTPCookiePath];
[cookieProperties setObject:@"0" forKey:NSHTTPCookieVersion];
/// 設(shè)置失效時間,不要設(shè)置NSHTTPCookieDiscard(設(shè)置sessionOnly,會話操作使用)
[cookieProperties setObject:[NSDate date] forKey:NSHTTPCookieExpires];
NSHTTPCookie *cookie = [NSHTTPCookie cookieWithProperties:cookieProperties];

其中有個需要注意的點,設(shè)置失效時間時,不要設(shè)置NSHTTPCookieDiscard。同時設(shè)置的話,失效時間會為nil,因為NSHTTPCookieDiscard 僅在會話操作時使用。

二、Cookie的注入

對于iOS11之前的系統(tǒng),可以直接使用 NSHTTPCookieStorage 來注入 Cookie,如下:

NSMutableDictionary *cookieProperties = [NSMutableDictionary dictionary];
[cookieProperties setObject:@"name" forKey:NSHTTPCookieName];
[cookieProperties setObject:@"value" forKey:NSHTTPCookieValue];
[cookieProperties setObject:@"jianshu.com" forKey:NSHTTPCookieDomain];
[cookieProperties setObject:@"jianshu.com" forKey:NSHTTPCookieOriginURL];
[cookieProperties setObject:@"/" forKey:NSHTTPCookiePath];
[cookieProperties setObject:@"0" forKey:NSHTTPCookieVersion];
/// 設(shè)置失效時間,不要設(shè)置NSHTTPCookieDiscard(設(shè)置sessionOnly,會話操作使用)
    [cookieProperties setObject:[NSDate date] forKey:NSHTTPCookieExpires];
    NSHTTPCookie *cookie = [NSHTTPCookie cookieWithProperties:cookieProperties];
    [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:cookie];

對于iOS11及之后的系統(tǒng),需要將 NSHTTPCookieStorage中的Cookie信息復(fù)制到 WKHTTPCookieStore 中,以此來達到 WKWebView中注入Cookie 的目的。

這是利用iOS11 API WKHTTPCookieStore 可以解決WKWebView首次請求不攜帶Cookie 的問題。因為WKWebView每次請求都會攜帶WKHTTPCookieStore里的Cookie。

只需要在上述代碼之后加入以下代碼即可:

if (@available(iOS 11, *)) {
    NSArray *cookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies];
    WKHTTPCookieStore *cookieStore = webview.configuration.websiteDataStore.httpCookieStore;
    for (NSHTTPCookie *cookie in cookies) {
        [cookieStore setCookie:cookie completionHandler:nil];
    }
    [cookieStore setCookie:cookie completionHandler:nil];
}
三、Cookie的刪除

iOS11之前的系統(tǒng)可以使用下面的方法來刪除Cookie:

[[WKWebsiteDataStore defaultDataStore] fetchDataRecordsOfTypes:[NSSet setWithObjects:WKWebsiteDataTypeCookies, nil] completionHandler:^(NSArray<WKWebsiteDataRecord *> * _Nonnull records) {
     [[WKWebsiteDataStore defaultDataStore] removeDataOfTypes:[WKWebsiteDataStore allWebsiteDataTypes] forDataRecords:records completionHandler:^{

    }];
}];

NSArray * cookArray = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies];
for (NSHTTPCookie *cookie in cookArray) {
    if ([cookie.domain isEqualToString:@"jianshu.com"]) {
        [[NSHTTPCookieStorage sharedHTTPCookieStorage] deleteCookie:cookie];
    }
}

iOS11及之后的系統(tǒng)可以使用WKHTTPCookieStore的deleteCookie: completionHandler: 方法來操作:

WKHTTPCookieStore *cookieStore = webview.configuration.websiteDataStore.httpCookieStore;
[cookieStore getAllCookies:^(NSArray* cookies) {
    for (NSHTTPCookie *cookie in cookies) {
        if ([cookie.domain isEqualToString:@"jianshu.com"]) {
            [cookieStore deleteCookie:cookie completionHandler:nil];
        }
    }
}];

以上。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容