Cookie簡介
說到Cookie,或許有些小伙伴會比較陌生,有些小伙伴會比較熟悉。如果項目中,所有頁面都是純原生來實現的話,一般Cookie這個東西或許我們永遠也不會接觸到。但是,這里還是要說一下Cookie,因為它真的很重要,由它產生的一些坑也很多。
Cookie 在 web中應用比較多,主要是記錄一個狀態,比如我在網頁上登錄了,我就可以拿到網頁登錄后 Cookie,下次再 Cookie 的生效期內我就可以不用輸入賬號密碼,直接跳轉登錄狀態,在App中,Cookie最常用的也就是維持登錄狀態了.因為筆者最近就在做這個,其中也遇到過很多坑,這里說先踩坑和用法
iOS Cookie 的管理
NSHTTPCookie和NSHTTPCookieStorage
iOS中進行HTTP網絡請求Cookie管理主要由兩個類負責,一個類是NSHTTPCookieStorage類,一個是NSHTTPCookie類。
NSHTTPCookieStorage
NSHTTPCookieStorage類采用單例的設計模式,其中管理着所有HTTP請求的Cookie信息
官方解釋:NSHTTPCookieStorage 是一個用來管理 cookie 存儲的單例。一個 NSHTTPCookie 單例代表一個 cookie。通常來講,cookie 可以在應用間共享,並且在進程之間保持同步。 對於單進程,Session cookies (這里的 cookie 對象的 isSessionOnly 方法返回 YES
)是局部的並且不能被共享。
常用方法
// 獲取單例對象
+ (NSHTTPCookieStorage *)sharedHTTPCookieStorage;
// 所有Cookie數據數組 其中存放NSHTTPCookie對象
@property (nullable , readonly, copy) NSArray<NSHTTPCookie *> *cookies;
// 手動設置一條Cookie數據
- (void)setCookie:(NSHTTPCookie *)cookie;
// 刪除某條Cookie信息
- (void)deleteCookie:(NSHTTPCookie *)cookie;
// 刪除某個時間后的所有Cookie信息 iOS8后可用
- (void)removeCookiesSinceDate:(NSDate *)date NS_AVAILABLE(10_10, 8_0);
// 獲取某個特定URL的所有Cookie數據
- (nullable NSArray<NSHTTPCookie *> *)cookiesForURL:(NSURL *)URL;
// 為某個特定的URL設置Cookie
- (void)setCookies:(NSArray<NSHTTPCookie *> *)cookies forURL:(nullable NSURL *)URL mainDocumentURL:(nullable NSURL *)mainDocumentURL;
// Cookie數據的接收協議
枚舉如下:
typedef NS_ENUM(NSUInteger, NSHTTPCookieAcceptPolicy) {
NSHTTPCookieAcceptPolicyAlways, //接收所有Cookie信息
NSHTTPCookieAcceptPolicyNever, //不接收所有Cookie信息
NSHTTPCookieAcceptPolicyOnlyFromMainDocumentDomain //只接收主文檔域的Cookie信息
};
@property NSHTTPCookieAcceptPolicy cookieAcceptPolicy;
系統下面的兩個通知與Cookie管理有關:
據說,在Mac OS是cookie可以共享的(Session cookies 不能共享),在Mac OS app中更改cookie的接收策略會影響到其他正在運行的在使用cookie storage的app.這時NSHTTPCookieStorage會發出兩個通知:
// Cookie數據的接收協議改變時發送的通知
FOUNDATION_EXPORT NSString * const NSHTTPCookieManagerAcceptPolicyChangedNotification;
// 管理的Cookie數據發生變化時發送的通知
FOUNDATION_EXPORT NSString * const NSHTTPCookieManagerCookiesChangedNotification;
NSHTTPCookie介紹
NSHTTPCookie是具體的HTTP請求Cookie數據對象.
// 下面兩個方法用於對象的創建和初始化 都是通過字典進行鍵值設置
- (nullable instancetype)initWithProperties:(NSDictionary<NSString *, id> *)properties;
+ (nullable NSHTTPCookie *)cookieWithProperties:(NSDictionary<NSString *, id> *)properties;
// 返回Cookie數據中可用於添加HTTP頭字段的字典
+ (NSDictionary<NSString *, NSString *> *)requestHeaderFieldsWithCookies:(NSArray<NSHTTPCookie *> *)cookies;
// 從指定的響應頭和URL地址中解析出Cookie數據
+ (NSArray<NSHTTPCookie *> *)cookiesWithResponseHeaderFields:(NSDictionary<NSString *, NSString *> *)headerFields forURL:(NSURL *)URL;
// Cookie數據中的屬性字典
@property (nullable, readonly, copy) NSDictionary<NSString *, id> *properties;
// 請求響應的版本
@property (readonly) NSUInteger version;
// 請求相應的名稱
@property (readonly, copy) NSString *name;
// 請求相應的值
@property (readonly, copy) NSString *value;
// 過期時間
@property (nullable, readonly, copy) NSDate *expiresDate;
// 請求的域名
@property (readonly, copy) NSString *domain;
//請求的路徑
@property (readonly, copy) NSString *path;
// 是否是安全傳輸
@property (readonly, getter=isSecure) BOOL secure;
// 是否只發送HTTP的服務
@property (readonly, getter=isHTTPOnly) BOOL HTTPOnly;
// 響應的文檔
@property (nullable, readonly, copy) NSString *comment;
// 相應的文檔URL
@property (nullable, readonly, copy) NSURL *commentURL;
// 服務端口列表
@property (nullable, readonly, copy) NSArray<NSNumber *> *portList;
HTTP cookie的屬性鍵
屬性 | 解讀
NSHTTPCookieName | Cookie的名字
NSHTTPCookieValue | Cookie的值
NSHTTPCookieOriginURL | 和域名一樣,NSHTTPCookieDomain或NSHTTPCookieOriginURL必須指定一個值
NSHTTPCookieVersion | 接收器的版本
NSHTTPCookieDomain | 域名
NSHTTPCookiePath | Cookie 存放路徑
NSHTTPCookieSecure | Cookie是否只應通過安全通道發送,設置Cookie的secure屬性為true。
只會在HTTPS和SSL等安全協議中傳輸此類Cookie。默認為false
NSHTTPCookieComment | 包含Cookie的評論,只有有效的版本1的cookies或更高版本。 這頭字段是可選的
NSHTTPCookieCommentURL | 接收器的評論URL
NSHTTPCookieDiscard | Cookie是否應在會議結束時丟棄NSString,字符串值必須是“true”或“假”。
這個字段是可選的。 默認為“假”,除非這是Cookie是第1版或以上,
NSHTTPCookieMaximumAge未指定,在這種情況下,它被假定為“TRUE”
NSHTTPCookieMaximumAge | NSString對象,包含一個整數,在Cookie內保持最多幾秒 。
僅適用於第1版和更高版本的有效。 默認為“0”。 此字段是可選的
NSHTTPCookiePort | 接收機的端口
- UIWebView的 Cookie 機制
UIWebView 在瀏覽網頁后會將網頁中的 cookie 自動存入 NSHTTPCookieStorage 標准容器中,[NSHTTPCookieStorage sharedHTTPCookieStorage]這個單例管理,在后續訪問中會將 cookie 自動帶到 request 請求當中。並且在同一個app內多個UIWebView之間共享。
- webView 中獲取 cookie
//加載成功
- (void)webViewDidFinishLoad:(UIWebView *)webView {
NSString *requestUrl = webView.request.URL.absoluteString;
NSLog(@" requestUrl: %@",requestUrl);
//設置原始 cookie 根據key 存儲本地
NSMutableArray *cookieArray = [[NSMutableArray alloc] init];
//網頁加載完成取出 cookies
NSArray *nCookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies];
NSHTTPCookie *cookie;
for (id c in nCookies) {
if ([c isKindOfClass:[NSHTTPCookie class]]) {
cookie=(NSHTTPCookie *)c;
//我這里是cookie存入字典中 去重
if ([cookie value]) {
//如果 vaule 值不為 nil 存入字典中,
[self.mutableDic setValue:[cookie value] forKey:[cookie name]];
}
//設置原始 cookie
NSMutableDictionary *cookieProperties = [NSMutableDictionary dictionary];
[cookieProperties setObject:cookie.name forKey:NSHTTPCookieName];
[cookieProperties setObject:cookie.value forKey:NSHTTPCookieValue];
[cookieProperties setObject:cookie.domain forKey:NSHTTPCookieDomain];
[cookieProperties setObject:cookie.path forKey:NSHTTPCookiePath];
[cookieProperties setObject:[[NSDate date] dateByAddingTimeInterval:2629743] forKey:NSHTTPCookieExpires];
[cookieArray addObject:cookieProperties];
[[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:cookie];
}
}
//cookie 存入本地
[[NSUserDefaults standardUserDefaults] setObject:cookieArray forKey:@"cookieArray"];
[[NSUserDefaults standardUserDefaults] synchronize];
//下面 cookie 去重是為了得到 key=Value;形式的字符串,這里由於我有需求這樣做,實際中下面可以忽略
NSMutableString *cookieValue = [NSMutableString stringWithFormat:@""];
// cookie重復,先放到字典進行去重,再進行拼接
for (NSString *key in self.mutableDic) {
NSString *appendString = [NSString stringWithFormat:@"%@=%@;", key, [self.mutableDic valueForKey:key]];
[cookieValue appendString:appendString];
}
NSLog(@"######################## %@ ####################",cookieValue);
- 設置 cookie
NSMutableArray* cookieDictionary = [[NSUserDefaults standardUserDefaults] valueForKey:@"cookieArray"];
NSLog(@"cookie dictionary found is %@",cookieDictionary);
if (cookieDictionary)
{
for (NSInteger i = 0; i < cookieDictionary.count; i++)
{
NSLog(@"cookie found is %@",[cookieDictionary objectAtIndex:i]);
NSDictionary *cookieDic = [cookieDictionary objectAtIndex:i];
NSHTTPCookie *cookie = [NSHTTPCookie cookieWithProperties:cookieDic];
[[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:cookie];
}
}
//設置請求之前加載 cookie 確保 cookie 在請求頭之前設置
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:self.URLString] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10];
//加載網頁
[self.webView loadRequest:request];
- 刪除 cookie
// 清空 cookie
- (void)deleteCookie {
// 清空 cookie
NSHTTPCookieStorage *cookieJar = [NSHTTPCookieStorage sharedHTTPCookieStorage];
NSArray *_tmpArray = [NSArray arrayWithArray:[cookieJar cookies]];
for (id obj in _tmpArray) {
[cookieJar deleteCookie:obj];
}
}
- WKWebView 的 Cookie 機制
NSURLCache和NSHTTPCookieStroage無法操作(WKWebView)WebCore進程的緩存和Cookie
WKWebView實例將會忽略任何的默認網絡存儲器(NSURLCache, NSHTTPCookieStorage, NSCredentialStorage) 和一些標准的自定義網絡請求類(NSURLProtocol,等等.),WKWebView實例不會把Cookie存入到App標准的的Cookie容器(NSHTTPCookieStorage)中,因為 NSURLSession/NSURLConnection等網絡請求使用NSHTTPCookieStorage進行訪問Cookie,所以不能訪問WKWebView的Cookie,現象就是WKWebView存了Cookie,其他的網絡類如NSURLSession/NSURLConnection卻看不到。這是很多人的說法。
還有一種是說法是通過實踐發現 WKWebView 實例其實也會將 Cookie 存儲於 NSHTTPCookieStorage 中,但存儲時機有延遲,因為WKWebView內也有cookie的容器,而且每隔一段時間就和app側NSHTTPCookieStorage進行同步,而且這個同步是進程級別的同步,而且這個同步是單向。
至於以上兩種說法,最終WKWebView Cookie 問題在於 WKWebView 發起的請求不會自動帶上存儲於 NSHTTPCookieStorage 容器中的 Cookie。
-
iOS11
iOS11 的 API 可以解決該問題,只要是存在 WKHTTPCookieStore 里的 cookie,WKWebView 每次請求都會攜帶,存在 NSHTTPCookieStorage 的cookie,並不會每次都攜帶。於是會發生首次 WKWebView 請求不攜帶 Cookie 的問題。 -
ios 11 WKWebView cookie 的注入
在執行 -[WKWebView loadReques:] 前將 NSHTTPCookieStorage 中的內容復制到 WKHTTPCookieStore 中,以此來達到 WKWebView Cookie 注入的目的。示例代碼如下:
[self copyNSHTTPCookieStorageToWKHTTPCookieStoreWithCompletionHandler:^{
NSURL *url = [NSURL URLWithString:@"https://www.v2ex.com"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[_webView loadRequest:request];
}];
- (void)copyNSHTTPCookieStorageToWKHTTPCookieStoreWithCompletionHandler:(nullable void (^)())theCompletionHandler; {
NSArray *cookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies];
WKHTTPCookieStore *cookieStroe = self.webView.configuration.websiteDataStore.httpCookieStore;
if (cookies.count == 0) {
!theCompletionHandler ?: theCompletionHandler();
return;
}
for (NSHTTPCookie *cookie in cookies)
{
[cookieStroe setCookie:cookie completionHandler:^{
if ([[cookies lastObject] isEqual:cookie])
{
!theCompletionHandler ?: theCompletionHandler();
return;
}
}];
}
}
-
ios11 之前
注入 Cookie 就是從之前保存 cookie 的 NSHTTPCookieStorage 中取出相關 Cookie,然后在再次請求訪問的時候在 request 中注入 Cookie。注入Cookie同樣有多種方式。 -
1.JS注入1
//取出 storage 中的cookie並將其拼接成正確的形式
NSArray<NSHTTPCookie *> *tmp = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies];
NSMutableString *jscode_Cookie = [@"" mutableCopy];
[tmp enumerateObjectsUsingBlock:^(NSHTTPCookie * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop)
{
NSLog(@"%@ = %@", obj.name, obj.value);
[jscode_Cookie appendString:[NSString stringWithFormat:@"document.cookie = '%@=%@';", obj.name, obj.value]];
}];
WKUserContentController* userContentController = WKUserContentController.new;
WKUserScript * cookieScript = [[WKUserScript alloc] initWithSource: @"" injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO];
[userContentController addUserScript:cookieScript];
WKWebViewConfiguration* webViewConfig = WKWebViewConfiguration.new;
webViewConfig.userContentController = userContentController;
WKWebView * webView = [[WKWebView alloc] initWithFrame:CGRectMake(/*set your values*/) configuration:webViewConfig];
- JS注入2
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation
{
[webView evaluateJavaScript:@"document.cookie ='TeskCookieKey1=TeskCookieValue1';" completionHandler:^(id result, NSError *error) {
//...
}];
}
- NSMutableURLRequest 注入Cookie
NSURL *url = request.URL;
NSMutableString *cookies = [NSMutableString string];
NSMutableURLRequest *requestObj = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10];
NSArray *tmp = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies];
NSDictionary *dicCookies = [NSHTTPCookie requestHeaderFieldsWithCookies:tmp];
NSString *cookie = [self readCurrentCookie];
[requestObj setValue:cookie forHTTPHeaderField:@"Cookie"];
[_webView loadRequest:requestObj];
-(NSString *)readCurrentCookie
{
NSMutableDictionary *cookieDic = [NSMutableDictionary dictionary];
NSMutableString *cookieValue = [NSMutableString stringWithFormat:@""];
NSHTTPCookieStorage *cookieJar = [NSHTTPCookieStorage sharedHTTPCookieStorage];
for (NSHTTPCookie *cookie in [cookieJar cookies]) {
[cookieDic setObject:cookie.value forKey:cookie.name];
}
// cookie重復,先放到字典進行去重,再進行拼接
for (NSString *key in cookieDic) {
NSString *appendString = [NSString stringWithFormat:@"%@=%@;", key, [cookieDic valueForKey:key]];
[cookieValue appendString:appendString];
}
return cookieValue;
}
獲取Cookie
由於 WKWebView 的 Cookie 存儲容器 WKWebsiteDataStore 是私有存儲,所以無法從這里獲取到Cookie,目前的方法是(1)從網站返回的 response headerfields 中獲取。(2)通過調用js的方法獲取 cookie。
- 1.從網站返回的 response headerfields 中獲取,因為cookie都存在http respone的headerfields,找到能獲得respone的WKWebView回調,打印
- (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];
//讀取wkwebview中的cookie 方法1
for (NSHTTPCookie *cookie in cookies) {
// [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:cookie];
NSLog(@"wkwebview中的cookie:%@", cookie);
}
//讀取wkwebview中的cookie 方法2 讀取Set-Cookie字段
NSString *cookieString = [[response allHeaderFields] valueForKey:@"Set-Cookie"];
NSLog(@"wkwebview中的cookie:%@", cookieString);
//看看存入到了NSHTTPCookieStorage了沒有
NSHTTPCookieStorage *cookieJar2 = [NSHTTPCookieStorage sharedHTTPCookieStorage];
for (NSHTTPCookie *cookie in cookieJar2.cookies) {
NSLog(@"NSHTTPCookieStorage中的cookie%@", cookie);
}
//下面是將 原始cookie本地 化
NSMutableArray *cookieArray = [[NSMutableArray alloc] init];
for (NSHTTPCookie *cookie in [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies]) {
NSMutableDictionary *cookieProperties = [NSMutableDictionary dictionary];
[cookieProperties setObject:cookie.name forKey:NSHTTPCookieName];
[cookieProperties setObject:cookie.value forKey:NSHTTPCookieValue];
[cookieProperties setObject:cookie.domain forKey:NSHTTPCookieDomain];
[cookieProperties setObject:cookie.path forKey:NSHTTPCookiePath];
[cookieProperties setObject:[NSNumber numberWithInt:cookie.version] forKey:NSHTTPCookieVersion];
[cookieProperties setObject:[[NSDate date] dateByAddingTimeInterval:2629743] forKey:NSHTTPCookieExpires];
[cookieArray addObject:cookieProperties];
}
[[NSUserDefaults standardUserDefaults] setValue:cookieArray forKey:@"cookieArray"];
[[NSUserDefaults standardUserDefaults] synchronize];
decisionHandler(WKNavigationResponsePolicyAllow);
}
// 頁面加載完成之后調用需要重新給WKWebView設置Cookie防止因為a標簽跳轉,導致下一次跳轉的時候Cookie丟失。
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation{
//取出cookie
NSHTTPCookieStorage *cookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
//js函數
NSString *JSFuncString =
@"function setCookie(name,value,expires)\
{\
var oDate=new Date();\
oDate.setDate(oDate.getDate()+expires);\
document.cookie=name+'='+value+';expires='+oDate+';path=/'\
}\
function getCookie(name)\
{\
var arr = document.cookie.match(new RegExp('(^| )'+name+'=({FNXX==XXFN}*)(;|$)'));\
if(arr != null) return unescape(arr[2]); return null;\
}\
function delCookie(name)\
{\
var exp = new Date();\
exp.setTime(exp.getTime() - 1);\
var cval=getCookie(name);\
if(cval!=null) document.cookie= name + '='+cval+';expires='+exp.toGMTString();\
}";
//拼湊js字符串
NSMutableString *JSCookieString = JSFuncString.mutableCopy;
for (NSHTTPCookie *cookie in cookieStorage.cookies) {
NSString *excuteJSString = [NSString stringWithFormat:@"setCookie('%@', '%@', 1);", cookie.name, cookie.value];
[JSCookieString appendString:excuteJSString];
}
//執行js
[webView evaluateJavaScript:JSCookieString completionHandler:^(id obj, NSError * _Nullable error) {
NSLog(@"%@",error);
}];
}
- 通過 JS 獲取 cookie
- (void)webView:(WKWebView *)webView didFinishNavigation:(null_unspecified WKNavigation *)navigation {
[webView evaluateJavaScript:[NSString stringWithFormat:@"document.cookie"] completionHandler:^(id _Nullable response, NSError * _Nullable error) {
if (response != 0) {
NSLog(@"\n\n\n\n\n\n document.cookie%@,%@",response,error);
}
}];
}
注意
document.cookie 的方法獲取 cookie並不支持跨越獲取,如果設置 httponly則獲取不到 cookie
不論是(1)還是(2)方法,似乎都無法解決302請求的 Cookie 問題。舉例來說,假設你要訪問網站A,在A中點擊登錄,跳轉頁面到B地址,在B中完成登錄之后302跳轉回A網站。此時cookie是存在於B地址的 response 中的,在A地址的 response 中並沒有 cookie 的字段。然而我們只能獲取到A地址的 response ,無法截獲到B地址的response。因此獲取不到該類型網站的 cookie 。
由於我並沒有遇到302這樣的問題,所有看了下網上的資料,希望對遇到這個問題的小伙伴一下辦法,網上給出的解決辦法是:
- 1.加載一個本地為空的html,域名指向你的第一次加載的url的域名。
//加載本地html
[self.webView loadHTMLString:@"" baseURL:[NSURL URLWithString:@"https:/a.com"]];
- 2.通過以下方法,在第一次加載完成后,將需要設置的Cookies設置到WKWebView中,因為是加載的本地的html以下方法會立即執行。
// 頁面加載完成之后調用
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation{
if (isFirstLoaded) {
NSHTTPCookieStorage *cookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
//js函數
NSString *JSFuncString =
@"function setCookie(name,value,expires)\
{\
var oDate=new Date();\
oDate.setDate(oDate.getDate()+expires);\
document.cookie=name+'='+value+';expires='+oDate+';path=/'\
}";
//拼湊js字符串,按照自己的需求拼湊Cookie
NSMutableString *JSCookieString = JSFuncString.mutableCopy;
for (NSHTTPCookie *cookie in cookieStorage.cookies) {
if (![cookie.name isEqualToString:@"__cust"]) {
NSString *excuteJSString = [NSString stringWithFormat:@"setCookie('%@', '%@', 3);", cookie.name, cookie.value];
[JSCookieString appendString:excuteJSString];
}
}
//執行js
[webView evaluateJavaScript:JSCookieString completionHandler:^(id obj, NSError * _Nullable error)
{
//加載真正的第一次Request
[self loadRealRequest];
}];
}
}
如果cookie 存儲到本地獲取本地的 cookie
//修改從 storage 中讀取 cookie 的方法
-(NSString *)readCurrentCookie{
NSMutableArray* cookieDictionary = [[NSUserDefaults standardUserDefaults] valueForKey:@"cookieArray"];
NSLog(@"cookie dictionary found is %@",cookieDictionary);
for (int i=0; i < cookieDictionary.count; i++) {
NSLog(@"cookie found is %@",[cookieDictionary objectAtIndex:i]);
NSMutableDictionary* cookieDictionary1 = [[NSUserDefaults standardUserDefaults] valueForKey:[cookieDictionary objectAtIndex:i]];
NSHTTPCookie *cookie = [NSHTTPCookie cookieWithProperties:cookieDictionary1];
[[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:cookie];
}
NSMutableDictionary *cookieDic = [NSMutableDictionary dictionary];
NSMutableString *cookieValue = [NSMutableString stringWithFormat:@""];
NSHTTPCookieStorage *cookieJar = [NSHTTPCookieStorage sharedHTTPCookieStorage];
for (NSHTTPCookie *cookie in [cookieJar cookies]) {
[cookieDic setObject:cookie.value forKey:cookie.name];
}
// cookie重復,先放到字典進行去重,再進行拼接
for (NSString *key in cookieDic)
{
NSString *appendString = [NSString stringWithFormat:@"%@=%@;", key, [cookieDic valueForKey:key]];
[cookieValue appendString:appendString];
}
return cookieValue;
}
清除 cookie
#pragma mark - 清空cookie
-(void)deleCookie {
// NSHTTPCookieStorage *cookieJar = [NSHTTPCookieStorage sharedHTTPCookieStorage];
// NSArray *_tmpArray = [NSArray arrayWithArray:[cookieJar cookies]];
// for (id obj in _tmpArray) {
// [cookieJar deleteCookie:obj];
// }
if (@available(iOS 9.0, *)) {//iOS9及以上
WKWebsiteDataStore *dateStore = [WKWebsiteDataStore defaultDataStore];
[dateStore fetchDataRecordsOfTypes:[WKWebsiteDataStore allWebsiteDataTypes]
completionHandler:^(NSArray<WKWebsiteDataRecord *> * __nonnull records)
{
for (WKWebsiteDataRecord *record in records)
{
//取消備注,可以針對某域名做專門的清除,否則是全部清除
//if ( [record.displayName containsString:@"baidu"])
//{
[[WKWebsiteDataStore defaultDataStore] removeDataOfTypes:record.dataTypes
forDataRecords:@[record] completionHandler:^
{
NSLog(@"Cookies for %@ deleted successfully",record.displayName);
}];
//}
}
}];
}
else { //iOS9以下
NSString *libraryPath = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *cookiesFolderPath = [libraryPath stringByAppendingString:@"/Cookies"];
NSError *errors;
[[NSFileManager defaultManager] removeItemAtPath:cookiesFolderPath error:&errors];
}
}
最后
UIWebView 和 WKWebView 所遇到問題 cookie 同步,獲取,刪除,設置這些問題,目前就這么多解決辦法吧,我一開始嘗試用 WKWebView 獲取 cookie 但是最后遇到網頁跨域問題以及低版本兼容問題我還是換回 UIWebView 了,如果有更好的解決辦法可以在下面留言,謝謝!