当你访问一个网站时,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写法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
一.获取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 =[[NSOperationQueuealloc]init];
[NSURLConnection sendAsynchronousRequest:request
queue:queue
completionHandler:^(NSURLResponse*response,NSData *data,NSError *error){
//转换NSURLResponse成为HTTPResponse
NSHTTPURLResponse *HTTPResponse =(NSHTTPURLResponse*)response;
//获取headerfields
NSDictionary *fields= [HTTPResponseallHeaderFields];//原生NSURLConnection写法
// NSDictionary *fields = [operation.response allHeaderFields]; //afnetworking写法
NSLog(@"fields = %@",[fieldsdescription]);
//获取cookie方法1
// NSArray *cookies = [NSHTTPCookie cookiesWithResponseHeaderFields:fields forURL:url];
//获取cookie方法2
//NSString *cookieString = [[HTTPResponse allHeaderFields] valueForKey:@"Set-Cookie"];
//获取cookie方法3
NSHTTPCookieStorage*cookieJar =[NSHTTPCookieStoragesharedHTTPCookieStorage];
for (NSHTTPCookie*cookie in[cookieJar cookies]){
NSLog(@"cookie%@",cookie);
}
}];
}
2.AFNetworking 写法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
AFHTTPSessionManager*manager =[AFHTTPSessionManagermanager];
manager.responseSerializer= [AFCompoundResponseSerializerserializer];
//demo中的api返回的是html数据,不是json
[manager POST:@"http://dev.skyfox.org/cookie.php" parameters:nil progress:^(NSProgress* _NonnulluploadProgress){
} success:^(NSURLSessionDataTask* _Nonnulltask,id _NullableresponseObject){
NSLog(@"\n======================================\n");
NSDictionary*fields =((NSHTTPURLResponse*)task.response).allHeaderFields;
NSLog(@"fields = %@",[fieldsdescription]);
NSURL*url =[NSURL URLWithString:@"http://dev.skyfox.org/cookie.php"];
NSLog(@"\n======================================\n");
//获取cookie方法1
NSArray*cookies =[NSHTTPCookie cookiesWithResponseHeaderFields:fields forURL:url];
for(NSHTTPCookie*cookie incookies){
NSLog(@"cookie,name:= %@,valuie = %@",cookie.name,cookie.value);
}
NSLog(@"\n======================================\n");
// //获取cookie方法2
// NSString *cookies2 = [((NSHTTPURLResponse*)task.response) valueForKey:@"Set-Cookie"];
// NSLog(@"cookies2 = %@",[cookies2 description]);
} failure:^(NSURLSessionDataTask* _Nullabletask,NSError *_Nonnull error){
}];
二.清空Cookie
NSHTTPCookieStorage*cookieJar =[NSHTTPCookieStoragesharedHTTPCookieStorage];
NSArray*cookieArray =[NSArray arrayWithArray:[cookieJarcookies]];
for(NSHTTPCookie*obj incookieArray){
[cookieJar deleteCookie:obj];
}
三.手动设置Cookie 手动设置的Cookie不会自动持久化到沙盒
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
第一次请求手动设置个cookie
-(void)test1:(NSString*)urlString{
NSURL*url =[NSURL URLWithString:@"http://dev.skyfox.org/cookie.php"];
NSMutableURLRequest*request =[NSMutableURLRequest requestWithURL:url];
NSMutableDictionary*cookieProperties = [NSMutableDictionarydictionary];
[cookieProperties setObject:@"username" forKey:NSHTTPCookieName];
[cookieProperties setObject:@"my ios cookie" forKey:NSHTTPCookieValue];
[cookieProperties setObject:@"dev.skyfox.org" forKey:NSHTTPCookieDomain];
[cookieProperties setObject:@"dev.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];
[[NSHTTPCookieStoragesharedHTTPCookieStorage] setCookie:cookie];
[self.myWebView loadRequest:request];
}
//第二次请求会自动带上Cookie
-(IBAction)test2:(id)sender{
NSURL*url =[NSURL URLWithString:@"http://dev.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
[[NSHTTPCookieStoragesharedHTTPCookieStorage]setCookieAcceptPolicy:NSHTTPCookieAcceptPolicyNever];
五.Cookie的持久化存储
1.服务器端设置Cookie,以PHP为例
语法
setcookie(name,value,expire,path,domain,secure)
参数 | 描述 | name必需。规定 cookie 的名称。value必需。规定 cookie 的值。expire可选。规定 cookie 的有效期。path可选。规定 cookie 的服务器路径。domain可选。规定 cookie 的域名。secure可选。规定是否通过安全的 HTTPS 连接来传输 cookie。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输出
<NSHTTPCookieversion:0name:"TestCookie"value:"my+cookie+value"expiresDate:2016-04-0809:31:09+0000created:2016-04-0809:30:49+0000sessionOnly:FALSEdomain:"dev.skyfox.org"path:"/"isSecure:FALSE>
持久化到了文件中,地址是 沙盒的 /Library/Cookies/org.skyfox.iOS-Cookie.binarycookies
使用终端执行 BinaryCookieReader.py脚本 解析 org.skyfox.iOS-Cookie.binarycookies 结果如下:
Jakey-mini:CookiesJakey$python BinaryCookieReader.pyorg.skyfox.iOS-Cookie.binarycookies
#*************************************************************************#
# BinaryCookieReader: developed by Satishb3: http://www.securitylearn.net #
#*************************************************************************#
Cookie: TestPHPWriteCookie=php+write+my+cookie+value;domain=dev.skyfox.org;path=/;expires=Thu,08 Dec2016;
2.app端手动存储Cookie
如果没设置Cookie失效时间expiresDate:(null),sessionOnly:true,kill掉后系统不会自动保存Cookie,如果想持久化Cookie 模仿浏览器存住Cookie,使用NSUserDefaults存下即可,以下是一条Cookie输出
<NSHTTPCookieversion:0name:"TestCookie"value:"my+cookie+value"expiresDate:(null)created:2016-04-0809:33:34+0000sessionOnly:TRUEdomain:"dev.skyfox.org"path:"/"isSecure:FALSE>
手动保存
//合适的时机持久化Cookie
- (void)saveCookies{
NSData*cookiesData =[NSKeyedArchiver archivedDataWithRootObject:[[NSHTTPCookieStoragesharedHTTPCookieStorage] cookies]];
NSUserDefaults*defaults =[NSUserDefaultsstandardUserDefaults];
[defaults setObject: cookiesData forKey:@"org.skyfox.cookiesave"];
[defaultssynchronize];
}
//合适的时机加载持久化后Cookie 一般都是app刚刚启动的时候
-(void)loadSavedCookies{
NSArray*cookies =[NSKeyedUnarchiver unarchiveObjectWithData:[[NSUserDefaultsstandardUserDefaults] objectForKey:@"org.skyfox.cookiesave"]];
NSHTTPCookieStorage*cookieStorage = [NSHTTPCookieStoragesharedHTTPCookieStorage];
for(NSHTTPCookie*cookie incookies){
NSLog(@"cookie,name:= %@,valuie = %@",cookie.name,cookie.value);
}
}
http://www.skyfox.org/ios-url-request-cookie.html