2020-01-08

iOS開發(fā)之cookie

原創(chuàng)?面壁者LOGIC?發(fā)布于2018-12-19 19:01:42 ?

本文鏈接:https://blog.csdn.net/Bolted_snail/article/details/85105524

最近公司項(xiàng)目安全檢查檢測(cè)到緩存中的用戶名和密碼撑螺,雖然已經(jīng)加密泉孩,但還是不安全邪铲;所以公司要求用cookie或者token去請(qǐng)求數(shù)據(jù)瘾英。由于公司項(xiàng)目比較老,里面既用了ASIHTTPRequest框架厨内,又用了AFNetworking框架,發(fā)現(xiàn)其實(shí)這兩個(gè)框架默認(rèn)都是自動(dòng)保持cookie的,我們不用去刻意處理它(獲取與上傳)琅拌。但是由于想搞清楚還是研究了一下cookie,并用NSURLSession?摘刑、ASIHTTPRequest进宝、?AFNetworking自己手動(dòng)管理cookie。

cookie: 是網(wǎng)站服務(wù)端為了辯別用戶身份枷恕,在服務(wù)器端生生成并存儲(chǔ)在用戶本地終端(電腦党晋、手機(jī))上的數(shù)據(jù)。其實(shí)cookie主要是用來免密登錄的徐块,我們這只是通過用戶名和密碼獲取一個(gè)身份令牌未玻,用于后面的接口調(diào)用,更像是token胡控。

NSHTTPCookieStorage 管理cookie

NSHTTPCookieStorage提供了管理所有NSHTTPCookie對(duì)象的接口扳剿,在OS X里,cookie是在所有程序中共享的,而在iOS中,cookie只在當(dāng)當(dāng)前應(yīng)用中有效铜犬。舞终。Session Cookie(SessionOnly返回YES的Cookie)只能在單一進(jìn)程中使用。

NSHTTPCookieStorage可以獲取癣猾,刪除敛劝,設(shè)置單例里面的cookies,設(shè)置cookie的管理策略等纷宇。

//只讀的單例對(duì)象

@property(class, readonly, strong) NSHTTPCookieStorage *sharedHTTPCookieStorage;

//獲取里面的cookie對(duì)象數(shù)組

@property (nullable , readonly, copy) NSArray<NSHTTPCookie *> *cookies;

//添加cookie

- (void)setCookie:(NSHTTPCookie *)cookie;

//刪除cookie

- (void)deleteCookie:(NSHTTPCookie *)cookie;

//刪除某個(gè)日期之前的cookie

- (void)removeCookiesSinceDate:(NSDate *)date API_AVAILABLE(macos(10.10), ios(8.0), watchos(2.0), tvos(9.0));

//設(shè)置cookie的管理策略

@property NSHTTPCookieAcceptPolicy cookieAcceptPolicy;

//獲取對(duì)應(yīng)url返回的cookie數(shù)組

- (nullable NSArray<NSHTTPCookie *> *)cookiesForURL:(NSURL *)URL;

NSHTTPCookie里面有個(gè)properties的屬性夸盟,其組成如下:

<__NSArrayM0x283bec540>(<NSHTTPCookieversion:0name:JSESSIONIDvalue:A0787301B667F5E1C7B5BABAAE58B104expiresDate:'(null)'created:'2018-12-27 02:39:06 +0000'sessionOnly:TRUEdomain:192.168.1.121partition:nonesameSite:nonepath:/innerisSecure:FALSEisHTTPOnly:YES path:"/inner"isSecure:FALSE isHTTPOnly:YES>,<NSHTTPCookieversion:0name:tokenvalue:1545878346436_111_cd90cdd1-9938-4e18-8ccd-79ad54d5527cexpiresDate:'2019-01-26 02:39:06 +0000'created:'2018-12-27 02:39:06 +0000'sessionOnly:FALSEdomain:192.168.1.121partition:nonesameSite:nonepath:/innerisSecure:FALSE path:"/inner"isSecure:FALSE>)

name必選規(guī)定 cookie 的名稱

value必選規(guī)定 cookie 的值

expire可選規(guī)定 cookie 的有效期

path可選規(guī)定 cookie 的服務(wù)器路徑,只有該路勁下的文件接口才能使用

domain可選規(guī)定 cookie 的域名

secure可選規(guī)定是否通過安全的 HTTPS 連接來傳輸 cookie

其中sessionOnly:TRUE的cookie是后臺(tái)服務(wù)器自動(dòng)創(chuàng)建的。

cookie和session默認(rèn)都是后臺(tái)創(chuàng)建像捶,后端會(huì)將cookie放在在response的header中返回給前端上陕,將session緩存在服務(wù)器中桩砰;前端獲取到cookie可以自己手動(dòng)保存,也可以交給NSHTTPCookieStorage單例來保存释簿;前端將cookie放在request的header中傳給服務(wù)器,服務(wù)器會(huì)去查對(duì)應(yīng)的session亚隅,然后去交換獲得用戶信息(用戶登錄ID等)請(qǐng)求接口,這就是整個(gè)cookie獲取庶溶、設(shè)置和請(qǐng)求數(shù)據(jù)的流程煮纵。

獲取cookie的幾種方法:

//方式1 :? NSHTTPCookie獲取cookieNSArray*array=[NSHTTPCookie cookiesWithResponseHeaderFields:httpresponse.allHeaderFields forURLresponse.URL];for(NSHTTPCookie*cookieinarray){//保存到sharedHTTPCookieStorage中[[NSHTTPCookieStorage sharedHTTPCookieStorage]setCookie:cookie];}//方式2:NSHTTPURLResponse獲取NSHTTPURLResponse*httpresponse=(NSHTTPURLResponse*)response;NSDictionary*dic=httpresponse.allHeaderFields;//獲取cookie字符串NSString*cookiesStr=[dic valueForKey:@"Set-Cookie"];//方式3:NSHTTPCookieStorage獲取cookieNSArray*cookies=[[NSHTTPCookieStorage sharedHTTPCookieStorage]cookiesForURL:response.URL];

多個(gè)cookie的格式通常為:cookie1=value1; cookie2=value2; cookie3=value3; 這里特別要注意,多個(gè)cookie之間用分號(hào)+空格分隔開偏螺,不是&也不是單純的空格行疏。我所了解到的iOS設(shè)置Cookie的方法有兩種。

設(shè)置cookie方式1:NSDictionary * dic = httpresponse.allHeaderFields;返回的字典有個(gè)"Set-Cookie"的字符串值就是多個(gè)cookie的默認(rèn)樣式套像,我們獲取到后可以直接設(shè)置cookie到request的 header中酿联。

{

? ? "Cache-Control" = "no-cache,must-revalidate";

? ? "Content-Length" = 7;

? ? Date = "Thu, 27 Dec 2018 07:11:51 GMT";

? ? Expires = "Thu, 01 Jan 1970 00:00:00 GMT";

? ? Pragma = "no-cache";

? ? Server = "Apache-Coyote/1.1";

? ? "Set-Cookie" = "JSESSIONID=D6F65DA599B3B6B22C1927C5D85B53F0; Path=/inner; HttpOnly, token=1545894711778_111_17906b71-9c77-48c5-8e5a-b9e52522a538; Expires=Sat, 26-Jan-2019 07:11:51 GMT; Path=/inner";

}

NSString * cookiesStr = [dic valueForKey:@"Set-Cookie"];

//設(shè)置cookies

[request setValue:cookiesaStr forHTTPHeaderField:@"Cookie"];

設(shè)置cookie方式2:構(gòu)建多個(gè)NSHTTPCookie實(shí)例對(duì)象的數(shù)組,根據(jù)NSHTTPCookie實(shí)例數(shù)組生成對(duì)應(yīng)的HTTP cookie header夺巩,設(shè)置cookie到request的header中贞让。

NSDictionary *properties1 = [NSDictionary dictionaryWithObjectsAndKeys:

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? @"domain.com", NSHTTPCookieDomain,

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? @"/", NSHTTPCookiePath,

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? @"userid", NSHTTPCookieName,

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? strUserId, NSHTTPCookieValue,

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? nil];


? ? NSDictionary *properties2 = [NSDictionary dictionaryWithObjectsAndKeys:

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? @"domain.com", NSHTTPCookieDomain,

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? @"/", NSHTTPCookiePath,

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? @"pid", NSHTTPCookieName,

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? pid, NSHTTPCookieValue,

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? nil];



? ? NSHTTPCookie *cookie1 = [NSHTTPCookie cookieWithProperties:properties1];

? ? NSHTTPCookie *cookie2 = [NSHTTPCookie cookieWithProperties:properties2];

? ? NSArray* cookies = [NSArray arrayWithObjects: cookie1, cookie2, nil];

? ? //根據(jù)NSHTTPCookie實(shí)例數(shù)組生成對(duì)應(yīng)的HTTP cookie header

? ? NSDictionary * headers = [NSHTTPCookie requestHeaderFieldsWithCookies:cookies];

? ? //設(shè)置cookie到header中

? ? request.allHTTPHeaderFields = headers;

NSURLSession管理cookie

NSURLSession中有兩個(gè)+ (NSURLSession *)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration;初始化方法,這個(gè)configuration可以給NSURLSession實(shí)例對(duì)象配置一下屬性策略等,與cookie有關(guān)的屬性有下:

//發(fā)送請(qǐng)求時(shí)是否設(shè)置cookie

@property BOOL HTTPShouldSetCookies;

//設(shè)置cookie的接收策略

@property NSHTTPCookieAcceptPolicy HTTPCookieAcceptPolicy;

typedef NS_ENUM(NSUInteger, NSHTTPCookieAcceptPolicy) {

? ? NSHTTPCookieAcceptPolicyAlways,//接收所有的cookie,默認(rèn)策略.

? ? NSHTTPCookieAcceptPolicyNever,//不接收所有的cookie

? ? NSHTTPCookieAcceptPolicyOnlyFromMainDocumentDomain//只接收main document domain中的cookie.

};

//保存設(shè)置cookie的劲够,如果不設(shè)置默認(rèn)是[NSHTTPCookieStorage sharedHTTPCookieStorage]震桶,設(shè)置為nil管理cookie

@property (nullable, retain) NSHTTPCookieStorage *HTTPCookieStorage;

所以NSURLSession多了一種設(shè)置cookie的方式,只要設(shè)置了HTTPCookieStorage屬性就可以自動(dòng)設(shè)置了cookie征绎。

1.使用系統(tǒng)管理cookie的類NSHTTPCookieStorage管理cookie

我們請(qǐng)求完成后必須手動(dòng)將cookie保存到[NSHTTPCookieStorage sharedHTTPCookieStorage]中蹲姐,不會(huì)自動(dòng)將響應(yīng)體header中的cookie保存,下面是具體實(shí)例人柿。

//獲取cookie

- (void)getCookies1{

? ? NSURL * url = [NSURL URLWithString:@"http://192.168.1.121:8080/inner/mobile/actionSh/Abc!login.action?"];

? ? NSString * post = [NSString stringWithFormat:@"loginId=%@",@"111"];

? ? NSData * postData = [post dataUsingEncoding:NSUTF8StringEncoding];

? ? NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:url];

? ? request.HTTPMethod = @"POST";

? ? request.HTTPBody = postData;

? ? //defaultSessionConfiguration 使用默認(rèn)session配置柴墩,類似NSURLConnection的標(biāo)準(zhǔn)配置,使用硬盤來存儲(chǔ)緩存數(shù)據(jù)凫岖,會(huì)將緩存江咳、cookie等存在本地

? ? //ephemeralSessionConfiguration 臨時(shí)session配置,與默認(rèn)配置相比哥放,不使用永久持存cookie歼指、證書、緩存的配置甥雕,最佳優(yōu)化數(shù)據(jù)傳輸踩身。

? ? //backgroundSessionConfiguration 后臺(tái)session配置,與默認(rèn)配置類似社露,不同的是會(huì)在后臺(tái)開啟另一個(gè)線程來處理網(wǎng)絡(luò)數(shù)據(jù)

? ? NSURLSessionConfiguration * defultConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];

? ? //不允許設(shè)置cookie

? ? defultConfiguration.HTTPShouldSetCookies = NO;

? ? //設(shè)置不允許緩存cookiechelue

? ? defultConfiguration.HTTPCookieAcceptPolicy = NSHTTPCookieAcceptPolicyNever;

? ? //清除所有的cookie

? ? for(NSHTTPCookie *cookie in [NSHTTPCookieStorage sharedHTTPCookieStorage].cookies)

? ? {

? ? ? ? [[NSHTTPCookieStorage sharedHTTPCookieStorage] deleteCookie: cookie];

? }

? ? NSLog(@"清除所有的cookies : %@",[NSHTTPCookieStorage sharedHTTPCookieStorage].cookies);

? ? defultConfiguration.HTTPCookieStorage = nil;

? ? NSURLSession * session = [NSURLSession sessionWithConfiguration:defultConfiguration delegate:nil delegateQueue:[NSOperationQueue currentQueue]];

? ? NSURLSessionTask * task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {

? ? ? ? NSLog(@"請(qǐng)求完成P琛!!");

? ? ? ? if (!error) {

? ? ? ? ? ? NSString * result = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];

? ? ? ? ? ? if (result) {

? ? ? ? ? ? ? ? NSLog(@"解析成功:%@",result);

? ? ? ? ? ? ? ? NSLog(@"response:%@",response);

? ? ? ? ? ? ? ? NSHTTPURLResponse * httpresponse = (NSHTTPURLResponse *)response;

? ? ? ? ? ? ? ? NSDictionary * dic = httpresponse.allHeaderFields;

//? ? ? ? ? ? ? ? NSString * cookies = [dic valueForKey:@"Set-Cookie"];

//? ? ? ? ? ? ? ? NSLog(@"cookies : %@ --- %@",cookies,[NSThread currentThread]);

//? ? ? ? ? ? ? ? NSArray * NSArray = [[NSHTTPCookieStorage sharedHTTPCookieStorage]cookiesForURL:response.URL];

? ? ? ? ? ? ? ? //獲取cookie

? ? ? ? ? ? ? NSArray * array = [NSHTTPCookie cookiesWithResponseHeaderFields:dic forURL:response.URL];

? ? ? ? ? ? ? ? for (NSHTTPCookie * cookie in array) {

? ? ? ? ? ? ? ? ? ? //保存到sharedHTTPCookieStorage中

? ? ? ? ? ? ? ? ? ? [[NSHTTPCookieStorage sharedHTTPCookieStorage]setCookie:cookie];

? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? NSLog(@"NSHTTPCookieStorage :? %@",[NSHTTPCookieStorage sharedHTTPCookieStorage].cookies);


? ? ? ? ? ? }else{

? ? ? ? ? ? ? ? NSLog(@"解析失敗!!!");

? ? ? ? ? ? }

? ? ? ? }else{

? ? ? ? ? ? NSLog(@"請(qǐng)求失敗 : %@",error.localizedDescription);

? ? ? ? }

? ? }];

? ? [task resume];

}

//設(shè)置cookie

- (void)requestWithCookies1{

? ? NSString * urlStr = @"http://192.168.1.121:8080/inner/mobile/actionSh/Abc!getData.action?";

? ? //encode去掉中午和特殊字符

? ? urlStr = [urlStr stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];

? ? NSURL * url = [NSURL URLWithString:urlStr];

? ? NSURLRequest * request = [NSURLRequest requestWithURL:url];

? ? NSURLSessionConfiguration * defultConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];

? ? defultConfiguration.HTTPShouldSetCookies = YES;

? ? defultConfiguration.HTTPCookieAcceptPolicy = NSHTTPCookieAcceptPolicyAlways;

? ? NSLog(@"NSHTTPCookieStorage :? %@",[NSHTTPCookieStorage sharedHTTPCookieStorage].cookies);

? ? defultConfiguration.HTTPCookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage];

? ? NSURLSession * session = [NSURLSession sessionWithConfiguration:defultConfiguration delegate:nil delegateQueue:[NSOperationQueue currentQueue]];

? ? NSURLSessionTask * task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {

? ? ? ? NSLog(@"請(qǐng)求完成8礁搿M哑础!");

? ? ? ? if (!error) {

? ? ? ? ? ? NSString * result = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];

? ? ? ? ? ? if (result) {

? ? ? ? ? ? ? ? NSLog(@"解析成功:%@",result);

? ? ? ? ? ? }else{

? ? ? ? ? ? ? ? NSLog(@"解析失敗!!!");

? ? ? ? ? ? }

? ? ? ? }else{

? ? ? ? ? ? NSLog(@"請(qǐng)求失敗 : %@",error.localizedDescription);

? ? ? ? }

? ? }];

? ? [task resume];

}

2.自己手動(dòng)管理cookie

上面的方法有時(shí)候并不能立即將cookie設(shè)置進(jìn)去坷备,所以我們自己手動(dòng)管理cookie比較保險(xiǎn)熄浓,就是在request的header中設(shè)置cookie,在response的header中獲取到得cookie保存到偏好設(shè)置或單例中自己管理省撑。

//獲取cookie

- (void)getCookies2{

? ? NSURL * url = [NSURL URLWithString:@"http://192.168.1.121:8080/inner/mobile/actionSh/Abc!login.action?"];

? ? NSString * post = [NSString stringWithFormat:@"loginId=%@",@"111"];

? ? NSData * postData = [post dataUsingEncoding:NSUTF8StringEncoding];

? ? NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:url];

? ? request.HTTPMethod = @"POST";

? ? request.HTTPBody = postData;

? ? NSURLSessionConfiguration * defultConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];

? ? //不允許設(shè)置cookie

? ? defultConfiguration.HTTPShouldSetCookies = NO;

? ? //不接受cookie

? ? defultConfiguration.HTTPCookieAcceptPolicy = NSHTTPCookieAcceptPolicyNever;


? ? NSURLSession * session = [NSURLSession sessionWithConfiguration:defultConfiguration delegate:nil delegateQueue:[NSOperationQueue currentQueue]];

? ? NSURLSessionTask * task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {

? ? ? ? NSLog(@"請(qǐng)求完成S褡椤!丁侄!");

? ? ? ? if (!error) {

? ? ? ? ? ? NSString * result = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];

? ? ? ? ? ? if (result) {

//? ? ? ? ? ? ? ? NSArray * cookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage]cookiesForURL:response.URL];

? ? ? ? ? ? ? ? NSLog(@"解析成功:%@",result);

? ? ? ? ? ? ? ? NSLog(@"response:%@",response);

? ? ? ? ? ? ? ? NSHTTPURLResponse * httpresponse = (NSHTTPURLResponse *)response;

? ? ? ? ? ? ? ? NSDictionary * dic = httpresponse.allHeaderFields;

? ? ? ? ? ? ? ? //獲取cookie字符串

? ? ? ? ? ? ? ? NSString * cookiesStr = [dic valueForKey:@"Set-Cookie"];

? ? ? ? ? ? ? ? NSData * cookiesData = [NSKeyedArchiver archivedDataWithRootObject:cookiesStr];

? ? ? ? ? ? ? ? //保存到偏好設(shè)置中

? ? ? ? ? ? ? ? [[NSUserDefaults standardUserDefaults] setValue:cookiesData forKey:@"BoncUserDefaultsCookie"];

? ? ? ? ? ? ? ? [[NSUserDefaults standardUserDefaults]synchronize];

? ? ? ? ? ? }else{

? ? ? ? ? ? ? ? NSLog(@"解析失敗!!!");

? ? ? ? ? ? }

? ? ? ? }else{

? ? ? ? ? ? NSLog(@"請(qǐng)求失敗 : %@",error.localizedDescription);

? ? ? ? }

? ? }];

? ? [task resume];

}

//設(shè)置cookie

- (void)requestWithCookies2{

? ? NSString * urlStr = @"http://192.168.1.121:8080/inner/mobile/actionSh/Abc!getData.action?";

? ? //encode去掉中午和特殊字符

? ? urlStr = [urlStr stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];

? ? NSURL * url = [NSURL URLWithString:urlStr];

? ? NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:url];

? ? NSData * cookiesData = [[NSUserDefaults standardUserDefaults] valueForKey:@"BoncUserDefaultsCookie"];

? ? NSString * cookiesaStr = [NSKeyedUnarchiver unarchiveObjectWithData:cookiesData];

? ? //設(shè)置cookies

? ? [request setValue:cookiesaStr forHTTPHeaderField:@"Cookie"];

? ? //如果是NSURLRequest,可用下面方式設(shè)置

//? ? request.allHTTPHeaderFields = nil;

? ? NSURLSessionConfiguration * defultConfiguration = [NSURLSessionConfiguration ephemeralSessionConfiguration];

? ? defultConfiguration.HTTPShouldSetCookies = NO;

? ? defultConfiguration.HTTPCookieAcceptPolicy = NSHTTPCookieAcceptPolicyNever;

? ? NSURLSession * session = [NSURLSession sessionWithConfiguration:defultConfiguration delegate:nil delegateQueue:[NSOperationQueue currentQueue]];

? ? NSURLSessionTask * task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {

? ? ? ? NSLog(@"請(qǐng)求完成!3住鸿摇!");

? ? ? ? if (!error) {

? ? ? ? ? ? NSString * result = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];

? ? ? ? ? ? if (result) {

? ? ? ? ? ? ? ? NSLog(@"解析成功:%@",result);

? ? ? ? ? ? }else{

? ? ? ? ? ? ? ? NSLog(@"解析失敗!!!");

? ? ? ? ? ? }

? ? ? ? }else{

? ? ? ? ? ? NSLog(@"請(qǐng)求失敗 : %@",error.localizedDescription);

? ? ? ? }

? ? }];

? ? [task resume];

}

AFNetworking自己管理cookie

AFNetworking是自動(dòng)保持cookie的,我們不用去刻意處理它(獲取與上傳)劈猿,除非你有一些需要拙吉。這里要講的是我們手動(dòng)管理cookie,AFNetworking中并沒有專門為cookie封裝的代碼揪荣,不過底層使用的是NSURLRequest筷黔,所以我們可以獲取到請(qǐng)求時(shí)服務(wù)器返回的cookie,然后保存起來(刪除和保存由我們自己管理),請(qǐng)求時(shí)候設(shè)置到request到header中即可仗颈。

設(shè)置不保持cookie

//默認(rèn)是YES佛舱,cookie會(huì)被存儲(chǔ)在共享的 NSHTTPCookieStorage 容器中

_manager.requestSerializer.HTTPShouldHandleCookies = NO;

獲取cookie,并保存起來

? ? ? // 獲取所有數(shù)據(jù)報(bào)頭信息

? ? ? ? NSHTTPURLResponse *HTTPResponse = (NSHTTPURLResponse *)task.response;

? ? ? ? NSDictionary *fields = [HTTPResponse allHeaderFields];

? ? ? ? // 獲取cookie

? ? ? ? NSString *cookieString = [fields valueForKey:@"Set-Cookie"];

? ? ? ? //保存到偏好設(shè)置中

? ? ? ? [[NSUserDefaults standardUserDefaults] setObject:cookieString forKey:@"BoncUserDefaultsCookie"];

? ? ? ? [[NSUserDefaults standardUserDefaults]synchronize];

設(shè)置cookie

? NSString * cookie = [[NSUserDefaults standardUserDefaults] valueForKey:@"BoncUserDefaultsCookie"];

? ? [self.manager.requestSerializer setValue:cookie forHTTPHeaderField:@"Cookie"];

ASIHTTPRequest自己管理cookie

ASIHTTPRequest是自動(dòng)保持cookie的,如果我們所用cookie請(qǐng)求數(shù)據(jù)挨决,默認(rèn)情況下我們不需要做其他任何操作请祖。不同于AFNetworking的是ASIHTTPRequest對(duì)cookie進(jìn)行了封裝,不管是獲取還是設(shè)置都及其方便脖祈,這里是我們自己管理cookie的做法肆捕。

設(shè)置不保持cookie

//默認(rèn)是YES,cookie會(huì)被存儲(chǔ)在共享的 NSHTTPCookieStorage 容器中盖高,并且會(huì)自動(dòng)被其他request重用慎陵。

request.useCookiePersistence = NO;

//清空session期間創(chuàng)建的所有cookie

//[ASIFormDataRequest setSessionCookies:nil];

//清除session期間產(chǎn)生的所有的cookie和緩存的授權(quán)數(shù)據(jù)。

// [ASIFormDataRequest clearSession];

獲取和保存cookie:

//獲取cookie

NSArray * cookies = [request responseCookies];

//獲取responseHeader

// NSDictionary *headers = [request responseHeaders];

//保存cookie

NSData * cookiesData = [NSKeyedArchiver archivedDataWithRootObject:cookies];

[[NSUserDefaults standardUserDefaults]setValue:cookiesData forKey:@"BoncUserDefaultsCookies"];

[[NSUserDefaults standardUserDefaults]synchronize];

設(shè)置cookie

? ? //依然要設(shè)置不保持cookie喻奥,否則傳遞cookie就不是我們自己保存到cookie

? ? [request setUseCookiePersistence:NO];

? ? //取出cookie

? ? NSData * cookiesData = [[NSUserDefaults standardUserDefaults] valueForKey:@"BoncUserDefaultsCookies"];

? ? NSArray * cookies = [NSKeyedUnarchiver unarchiveObjectWithData:cookiesData];

? ? //設(shè)置cookie

? ? [request setRequestCookies:cookies.mutableCopy];

AFNetworking和ASIHTTPRequest默認(rèn)都是開啟cookie的席纽,并且都是用[NSHTTPCookieStorage sharedHTTPCookieStorage]管理cookie的,所有二者可以通用映凳,我們這里手動(dòng)管理cookie,可以自己控制cookie的生命周期胆筒,避免過期的情況。其實(shí)默認(rèn)情況已經(jīng)夠我們正常使用了,這里需要注意點(diǎn)是默認(rèn)都是開啟cookie的情況下仆救,如在我們登錄獲取cookie時(shí)候抒和,一定要先清除cookie,否則可能出現(xiàn)退出登錄(不退出應(yīng)用)換了個(gè)用戶登錄彤蔽,登錄后的數(shù)據(jù)還是上個(gè)用戶的信息(未清除jsessionID)摧莽,雖然可以交給后臺(tái)取處理(后臺(tái)判斷是不是登錄接口,如果是就不取cookie),但我們客戶端也應(yīng)該處理一下顿痪,避免該錯(cuò)誤的發(fā)生镊辕。

AFNetworking請(qǐng)求登錄接口時(shí)候清除cookie:

AFHTTPSessionManager? * manager =? [AFHTTPSessionManager manager];

[manager.requestSerializer setValue:nil forHTTPHeaderField:@"Cookie"];

//有時(shí)候這樣設(shè)置并不好使,雖然也是在不保持cookie蚁袭,但[NSHTTPCookieStorage sharedHTTPCookieStorage]還是保持了cookie征懈,這樣jsessionID并沒有清除,所以為保險(xiǎn)起見要清空[NSHTTPCookieStorage sharedHTTPCookieStorage]里面的cookies

- (void)clearCookies{

? ? NSHTTPCookieStorage *cookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage];

? ? NSArray *_tmpArray = [NSArray arrayWithArray:[cookieStorage cookies]];

? ? for (id obj in _tmpArray) {

? ? ? ? [cookieStorage deleteCookie:obj];

? ? }

}

ASIHTTPRequest請(qǐng)求登錄接口時(shí)候清除cookie:

[ASIFormDataRequest setSessionCookies:nil];

UIWebView和WKWebView的cookie管理機(jī)制

UIWebView會(huì)將NSHttpRequest的所有請(qǐng)求產(chǎn)生的cookie自動(dòng)保存到NSHTTPCookieStorage容器中揩悄,并且在同一個(gè)app內(nèi)多個(gè)UIWebView之間共享卖哎,不需要我們做任何操作,在后續(xù)訪問中會(huì)將?cookie?自動(dòng)帶到request?請(qǐng)求當(dāng)中。

WKWebView的cookie問題在于?WKWebView發(fā)起的請(qǐng)求不會(huì)自動(dòng)帶上存儲(chǔ)于?NSHTTPCookieStorage容器中的Cookie,實(shí)踐發(fā)現(xiàn)WKWebView實(shí)例其實(shí)也會(huì)將cookie存儲(chǔ)于?NSHTTPCookieStorage?中删性,但存儲(chǔ)時(shí)機(jī)有延遲亏娜,在iOS 8上,當(dāng)頁面跳轉(zhuǎn)的時(shí)候蹬挺,當(dāng)前頁面的?cookie?會(huì)寫入NSHTTPCookieStorage中维贺,而在 iOS 10 上,JS 執(zhí)行?document.cookie?或服務(wù)器?set-cookie注入的?cookie會(huì)很快同步到?NSHTTPCookieStorage中,在執(zhí)行?[WKWebView loadReques:]?前將?NSHTTPCookieStorage中的內(nèi)容復(fù)制到?WKHTTPCookieStore中巴帮,以此來達(dá)到?WKWebView cookie注入的目的溯泣。

Demo下載地址:?OS開發(fā)之cookie研究demo

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市晰韵,隨后出現(xiàn)的幾起案子发乔,更是在濱河造成了極大的恐慌,老刑警劉巖雪猪,帶你破解...
    沈念sama閱讀 211,123評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件栏尚,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡只恨,警方通過查閱死者的電腦和手機(jī)译仗,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來官觅,“玉大人纵菌,你說我怎么就攤上這事⌒莸樱” “怎么了咱圆?”我有些...
    開封第一講書人閱讀 156,723評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵笛辟,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我序苏,道長(zhǎng)手幢,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,357評(píng)論 1 283
  • 正文 為了忘掉前任忱详,我火速辦了婚禮围来,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘匈睁。我一直安慰自己监透,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,412評(píng)論 5 384
  • 文/花漫 我一把揭開白布航唆。 她就那樣靜靜地躺著胀蛮,像睡著了一般。 火紅的嫁衣襯著肌膚如雪糯钙。 梳的紋絲不亂的頭發(fā)上醇滥,一...
    開封第一講書人閱讀 49,760評(píng)論 1 289
  • 那天,我揣著相機(jī)與錄音超营,去河邊找鬼。 笑死阅虫,一個(gè)胖子當(dāng)著我的面吹牛演闭,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播颓帝,決...
    沈念sama閱讀 38,904評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼米碰,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了购城?” 一聲冷哼從身側(cè)響起吕座,我...
    開封第一講書人閱讀 37,672評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎瘪板,沒想到半個(gè)月后吴趴,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,118評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡侮攀,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,456評(píng)論 2 325
  • 正文 我和宋清朗相戀三年锣枝,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片兰英。...
    茶點(diǎn)故事閱讀 38,599評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡撇叁,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出畦贸,到底是詐尸還是另有隱情陨闹,我是刑警寧澤,帶...
    沈念sama閱讀 34,264評(píng)論 4 328
  • 正文 年R本政府宣布,位于F島的核電站趋厉,受9級(jí)特大地震影響寨闹,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜觅廓,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,857評(píng)論 3 312
  • 文/蒙蒙 一鼻忠、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧杈绸,春花似錦帖蔓、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,731評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至劫侧,卻和暖如春埋酬,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背烧栋。 一陣腳步聲響...
    開封第一講書人閱讀 31,956評(píng)論 1 264
  • 我被黑心中介騙來泰國(guó)打工写妥, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人审姓。 一個(gè)月前我還...
    沈念sama閱讀 46,286評(píng)論 2 360
  • 正文 我出身青樓珍特,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親魔吐。 傳聞我的和親對(duì)象是個(gè)殘疾皇子扎筒,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,465評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容

  • iOS開發(fā)系列--網(wǎng)絡(luò)開發(fā) 概覽 大部分應(yīng)用程序都或多或少會(huì)牽扯到網(wǎng)絡(luò)開發(fā),例如說新浪微博酬姆、微信等嗜桌,這些應(yīng)用本身可...
    lichengjin閱讀 3,644評(píng)論 2 7
  • 在蘋果徹底棄用NSURLConnection之后自己總結(jié)的一個(gè)網(wǎng)上的內(nèi)容,加上自己寫的小Demo辞色,很多都是借鑒網(wǎng)絡(luò)...
    付寒宇閱讀 4,268評(píng)論 2 13
  • HTTP POST /ap HTTP/1.1 【請(qǐng)求行】Host: 192.168....
    nelsony66閱讀 277評(píng)論 0 0
  • 現(xiàn)在的農(nóng)村大變樣相满,農(nóng)民在經(jīng)濟(jì)上收入更多了诱篷,住的房子更好了■椋可人與人之間那純樸的感情不見了棕所。 近段時(shí)間讀到了一篇文章...
    一訪文閱讀 362評(píng)論 2 5
  • 法會(huì)期間,一些師兄師姐分享了自己的修行報(bào)告悯辙,與那些師兄師姐們相比琳省,我自覺汗顏無地迎吵,努力的程度,見地和境界针贬,都差得太...
    沛清0819閱讀 3,064評(píng)論 1 3