標籤:wrap iba content mac inter data rem cached 同步
當你訪問一個網站時,NSURLRequest都會幫你主動記錄下來你訪問的網站設定的Cookie,如果 Cookie 存在的話,會把這些資訊放在 NSHTTPCookieStorage 容器中共用,當你下次再訪問這個網站時,NSURLRequest會拿著上次儲存下來了的Cookie繼續去請求。
同樣適用於ASIHTTPRequest,AFNetworking, Webview等,Cookie常用於一些基於認證的網路請求
認識下NSHTTPCookieStorage
NSHTTPCookieStorage 實現了一個管理cookie的單例對象(只有一個執行個體),每個Cookie都是NSHTTPCookie類的執行個體,最為一個規則,Cookie在所有應用之間共用並在不同進程之間保持同步。Session Cookie(一個isSessionOnly方法返回YES的Cookie)只能在單一進程中使用。
Cookie
Cookie是由伺服器端產生,發送給User-Agent(一般是瀏覽器或者用戶端),瀏覽器會將Cookie的key/value儲存到某個目錄下的文字檔內,下次請求同一網站地址時就發送該Cookie給伺服器
HTTP header
HTTP header中包含HTTP請求與響應的巨集指令引數. header屬性定義了所傳輸資料的各種特性. header屬性以屬性名稱開始,以冒號結尾,最後是屬性值.屬性名稱及值會因應用的不同
一.iOS htttp網路請求Cookie的讀取與寫入:
Cookie必然會通過HTTP的Respone傳過來,並且Cookie在Respone中的HTTP header中。不管是什麼請求架構,必然會存在Respone對象,比如AFNetworking2.x的operation.response,AFNetworking3.x的task.response等等。。。。
1.原生NSURLConnection寫法
一.擷取cookie- (IBAction)cookieTouched:(id)sender { NSURL *url = [NSURL URLWithString:@"http://api.skyfox.org/api-test.php"]; NSURLRequest *request = [NSURLRequest requestWithURL:url] cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData timeoutInterval:3]; NSOperationQueue *queue = [[NSOperationQueue alloc] init]; [NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error){ //轉換NSURLResponse成為HTTPResponse NSHTTPURLResponse *HTTPResponse = (NSHTTPURLResponse *)response; //擷取headerfields NSDictionary *fields = [HTTPResponse allHeaderFields];//原生NSURLConnection寫法 // NSDictionary *fields = [operation.response allHeaderFields]; //afnetworking寫法 NSLog(@"fields = %@",[fields description]); //擷取cookie方法1 // NSArray *cookies = [NSHTTPCookie cookiesWithResponseHeaderFields:fields forURL:url]; //擷取cookie方法2 //NSString *cookieString = [[HTTPResponse allHeaderFields] valueForKey:@"Set-Cookie"]; //擷取cookie方法3 NSHTTPCookieStorage *cookieJar = [NSHTTPCookieStorage sharedHTTPCookieStorage]; for (NSHTTPCookie *cookie in [cookieJar cookies]) { NSLog(@"cookie%@", cookie); } }];}
2.AFNetworking 寫法
[[APIClient sharedClient] postPath:@"http://api.skyfox.org/api-test.php" parameters:p success:^(AFHTTPRequestOperation *operation, id JSON) { NSDictionary *fields = [operation.response allHeaderFields]; //afnetworking寫法 NSLog(@"fields = %@",[fields description]); NSURL *url = [NSURL URLWithString:@"http://api.skyfox.org/api-test.php"]; //擷取cookie方法1 NSArray *cookies = [NSHTTPCookie cookiesWithResponseHeaderFields:fields forURL:url]; //擷取cookie方法2 //NSString *cookieString = [[HTTPResponse allHeaderFields] valueForKey:@"Set-Cookie"]; } failure:^(AFHTTPRequestOperation *operation, NSError *error) { }];
二.清空Cookie
NSHTTPCookieStorage *cookieJar = [NSHTTPCookieStorage sharedHTTPCookieStorage]; NSArray *cookieArray = [NSArray arrayWithArray:[cookieJar cookies]]; for (id obj in cookieArray) { [cookieJar deleteCookie:obj]; }
三.手動設定Cookie 手動設定的Cookie不會自動持久化到沙箱
第一次請求手動設定個cookie-(void)test1:(NSString*)urlString{ NSURL *url = [NSURL URLWithString:@"http://api.skyfox.org/cookie.php"]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; NSMutableDictionary *cookieProperties = [NSMutableDictionary dictionary]; [cookieProperties setObject:@"username" forKey:NSHTTPCookieName]; [cookieProperties setObject:@"my ios cookie" forKey:NSHTTPCookieValue]; [cookieProperties setObject:@"api.skyfox.org" forKey:NSHTTPCookieDomain]; [cookieProperties setObject:@"api.skyfox.org" forKey:NSHTTPCookieOriginURL]; [cookieProperties setObject:@"/" forKey:NSHTTPCookiePath]; [cookieProperties setObject:@"0" forKey:NSHTTPCookieVersion]; [cookieProperties setObject:[NSDate dateWithTimeIntervalSinceNow:60*60] forKey:NSHTTPCookieExpires];//設定失效時間 [cookieProperties setObject:@"0" forKey:NSHTTPCookieDiscard]; //設定sessionOnly NSHTTPCookie *cookie = [NSHTTPCookie cookieWithProperties:cookieProperties]; [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:cookie]; [self.myWebView loadRequest:request];}//第二次請求會自動帶上Cookie- (IBAction)test2:(id)sender { NSURL *url = [NSURL URLWithString:@"http://api.skyfox.org/cookie.php"]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; [self.mywebview2 loadRequest:request];}
request還可以這樣設定個Cookie
[request setHTTPShouldHandleCookies:YES];[request setValue:[NSString stringWithFormat:@"%@=%@", [cookie name], [cookie value]] forHTTPHeaderField:@"Cookie"];
四.Cookie的本機快取策略
//NSHTTPCookieAcceptPolicyAlways:儲存所有cookie,這個是預設值//NSHTTPCookieAcceptPolicyNever:不儲存任何回應標頭中的cookie//NSHTTPCookieAcceptPolicyOnlyFromMainDocumentDomain:只儲存域請求匹配的cookie [[NSHTTPCookieStorage sharedHTTPCookieStorage]setCookieAcceptPolicy:NSHTTPCookieAcceptPolicyNever];
五.Cookie的持久化儲存1.伺服器端設定Cookie,以PHP為例文法
1 |
setcookie(name,value,expire,path,domain,secure) |
參數 |
描述 |
name |
必需。規定 cookie 的名稱。 |
value |
必需。規定 cookie 的值。 |
expire |
可選。規定 cookie 的有效期間。 |
path |
可選。規定 cookie 的伺服器路徑。 |
domain |
可選。規定 cookie 的網域名稱。 |
secure |
可選。規定是否通過安全的 HTTPS 串連來傳輸 cookie。 |
123 |
setcookie("TestCookie","my cookie value"); //沒設定失效時間 關閉app後系統不會持久化Cookie setcookie("TestCookie","my cookie value",time()+3600*24); //設定expire失效時間 關閉app後系統自動持久化Cookie |
如果伺服器設定了Cookie失效時間expiresDate ,sessionOnly:FALSE會被持久化到檔案中,kill掉後系統自動儲存,下次啟動app會自動載入.binarycookies中的Cookies,以下是一條Cookie輸出
1 |
<NSHTTPCookie version:0 name:"TestCookie" value:"my+cookie+value" expiresDate:2016-04-08 09:31:09+0000 created:2016-04-08 09:30:49 +0000 sessionOnly:FALSE domain:"api.skyfox.org" path:"/"isSecure:FALSE> |
持久化到了檔案中,地址是 沙箱的 /Library/Cookies/org.skyfox.AFNetworking-demo.binarycookies
使用BinaryCookieReader.py指令碼 解析 org.skyfox.AFNetworking-demo.binarycookies 結果如下
2.app端手動儲存Cookie
如果沒設定Cookie失效時間expiresDate:(null),sessionOnly:true,kill掉後系統不會自動儲存Cookie,如果想持久化Cookie 模仿瀏覽器存住Cookie,使用NSUserDefaults存下即可,以下是一條Cookie輸出
1 |
<NSHTTPCookie version:0 name:"TestCookie" value:"my+cookie+value" expiresDate:(null) created:2016-04-08 09:33:34 +0000 sessionOnly:TRUE domain:"api.skyfox.org" path:"/" isSecure:FALSE> |
手動儲存
//合適的時機儲存Cookie- (void)saveCookies{ NSData *cookiesData = [NSKeyedArchiver archivedDataWithRootObject: [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies]]; NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; [defaults setObject: cookiesData forKey: @"org.skyfox.cookie"]; [defaults synchronize];}//合適的時機載入Cookie 一般都是app剛剛啟動的時候- (void)loadCookies{ NSArray *cookies = [NSKeyedUnarchiver unarchiveObjectWithData: [[NSUserDefaults standardUserDefaults] objectForKey: @"org.skyfox.cookie"]]; NSHTTPCookieStorage *cookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage]; for (NSHTTPCookie *cookie in cookies){ [cookieStorage setCookie: cookie]; }}
iOS htttp網路請求cookie的讀取與寫入(NSHTTPCookieStorage)