(cookie使用支持的简单思路是:首次请求时,服务器取回cookies,然后每次请求时附加上cookie,如此反复即可,至于cookies中有啥内容,我们不用关注,服务器要就给她)
Cookie是浏览器访问一些网站后,这些网站存放在客户端的一组数据,用于使网络等跟踪用户,实现用户自定义功能。
Cookie的Domain和Path属性标识了这个Cookie是哪一个网站发送给浏览器的;Cookie的Expires属性标识Cookie的有效时间,当Cookie的有效时间过了之后,这些数据就被自动删除了。
如果不设置过期时间,则表示这个Cookie生命周期为浏览器会话期间,只要关闭浏览器窗口,Cookie就消失了,这种生命期为浏览会话期的Cookie被称为会话Cookie。会话Cookie一般不保存在硬盘上,而是保存在内存里,如果设置了过期时间,浏览器就会把Cookie保存到硬盘上,关闭后再次打开浏览器,这些Cookie依然有效,直到超过设定的过期时间,存储在硬盘上的Cookie就可以在不同的浏览器进程间共享,比如两个IE窗口,而对于保存在内存的Cookie,不同的浏览器有不同的处理方式。
Session是存放在服务器的类似于HashTable结构(每一种Web开发技术的实现可能不一样,下文直接称之为HashTable)来存放用户数据,当浏览器第一次发送请求时,服务器自动生成了一个HashTable和一个SessionID用来唯一标示这个HashTable,并将其通过响应发送到浏览器,当浏览器第二次发送请求,会将前一次服务器响应中的session ID放在请求中一并发送到服务器,服务器从请求中提取到Session ID,并和保存的所有Session ID进行对比,找到这个用户对应的HashTable。
一般情况下,服务器会在一定时间内(默认20分钟)保存这个TashTable,过了时间限制,就会销毁这个HashTable。在销毁之前,程序员可以将用户的一些数据以Key和Value的形式存放在这个HashTable中,当然,也有使这个HashTable序列化后保存起来的,这样的好处是没了时间的限制,坏处是随着时间的增加,这个数据库会急速膨胀,特别是访问量增加的时候,一般还是采取前一种方式,以减轻服务器压力。
Session的客户端实现形式(=session ID的保存方法)
一般浏览器提供两种方式来保存,还有一种是程序员使用Html隐藏的方式自定义实现。
1、使用Cookie来保存,这是最常见的方法,本文“记住我的登录状态”功能的实现正式基于这种方式的,服务器通过设置Cookie的方式将Session ID发送到浏览器,如果我们不设置这个过期时间,那么这个cookie将不存放在硬盘上,当浏览器关闭的时候,cookie就消失了,这个sessionID就丢失了。如果我们设置这个时间为若干天之后,那么这个Cookie会保存在客户端硬盘中,即使浏览器关闭,这是值仍然存在,下次访问相应网站时,同样会发送到服务器上。
2、使用URL附加信息的方式,也就是像我们经常看到的JSP网站会有aaa.jsp?JSESSIONID=*一样的。这种方式和第一种方式里面不设置Cookie过期时间是一样的。
3、第三种方式是在页面表单里面增加隐藏域,这种方式实际上和第二种方式一样,只不过前者通过Get方式发送数据,后者使用Post方式发送数据,但是明显后者比较麻烦。
Cookie与iOS
当你访问一个网站的时候,不管你愿意或者不愿意,NSURLRequset都会帮你主动记录下来你访问的站点设置的cookie,而且很负责任的,当你下次再访问这个站点时,NSURLRequest会拿着上次保存下来的cookie继续去请求,这规律同样适用于ASIHttpRequset。所以当你做一些基于认证的网络请求时,cookie不失为一个完美的解决方案。
NSHTTPCookieStorage *cookieJar = [NSHTTPCookieStorage sharedHTTPCookieStorage];
for (NSHTTPCookie *cookie in [cookieJar cookies]) {
NSLog(@"%@", cookie);
}
这样就列出了所有已保存的cookie,如果当前为空怎么办,随便请求一个url
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://blog.cnrainbird.com"]
cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData
timeoutInterval:3];
[NSURLConnection sendSynchronousRequest:request
returningResponse:nil
error:nil];
NSHTTPCookieStorage *cookieJar = [NSHTTPCookieStorage sharedHTTPCookieStorage];
for (NSHTTPCookie *cookie in [cookieJar cookies]) {
NSLog(@"%@", cookie);
}
log出<NSHTTPCookie version:0 name:"PHPSESSID" value:"evf5rcboo8th1dnl53fs4ukmt2" expiresDate:(null) created:2012-03-13 14:28:13 +0000 (3.53342e+08) sessionOnly:TRUE domain:"blog.cnrainbird.com" path:"/" isSecure:FALSE>
的东东就是cookie啦
怎么清空cookie呢?
NSHTTPCookieStorage *cookieJar = [NSHTTPCookieStorage sharedHTTPCookieStorage];
NSArray *_tmpArray = [NSArray arrayWithArray:[cookieJar cookies]];
for (id obj in _tmpArray) {
[cookieJar deleteCookie:obj];
}
这样cookie就消失的一干二净了
1
2 3 4 5 6 7 8 9 10 |
NSMutableDictionary *cookieProperties = [NSMutableDictionary dictionary];
[cookieProperties setObject:@"username" forKey:NSHTTPCookieName]; [cookieProperties setObject:@"rainbird" forKey:NSHTTPCookieValue]; [cookieProperties setObject:@"cnrainbird.com" forKey:NSHTTPCookieDomain]; [cookieProperties setObject:@"cnrainbird.com" forKey:NSHTTPCookieOriginURL]; [cookieProperties setObject:@"/" forKey:NSHTTPCookiePath]; [cookieProperties setObject:@"0" forKey:NSHTTPCookieVersion]; NSHTTPCookie *cookie = [NSHTTPCookie cookieWithProperties:cookieProperties]; [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:cookie]; |
1
|
<NSHTTPCookie version:0 name:"username" value:"rainbird" expiresDate:(null) created:2012-03-13 14:36:53 +0000 (3.53342e+08) sessionOnly:TRUE domain:"cnrainbird.com" path:"/" isSecure:FALSE>
|
下面我们通过一个demo来实践一下吧
来用两种登陆注册的写法来说明吧
第一种:用NSUserDefault
-(IBAction)tapLogin:(id)sender
{
//获取用户输入信息
NSString * username = self.usernameTextFiled.text;
NSString * password = self.passwordTextField.text;
//对用户信息的验证
if([username isEqualToString:password])
{
NSUserDefalut * userDefault = [NSUserDefalut standardUserDefaluts];
//登陆成功后把用户名和密码存储到UserDefault
[userDefaults setObject:username forKey:@"name"];
[userDefaults setObject:password forKey:@"password"];
//同步
[userDefaults synchronized];
//用模态跳转到主界面
UIStoryboard * storyboard = [UIStoryboard storyboardWithName:@"main" bundle:[NSBundle mainBundle]];
id mainViewController = [stroyboard instantiateViewControllerWithIdentifier:@"MainView"];
[self presentViewController:mainViewController animated:YES completion:^{
}];
}
}
处理完登陆界面,我们会处理根据UserDefault中的name属性是否有值来选择加载哪个页面,在stroyboard中我们默认的是主界面,在AppDelegate.m中如果未登录,我们会设置一下rootViewController,代码如下
//判断是否登陆,由登陆状态判断启动页面 //获取UserDefault NSUserDefaults *userDefault = [NSUserDefaults standardUserDefaults]; NSString *name = [userDefault objectForKey:@"name"]; //获取storyboard UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]]; //如果用户未登陆则把根视图控制器改变成登陆视图控制器 if (name == nil) { NSLog(@"%@",name); id view = [storyboard instantiateViewControllerWithIdentifier:@"LoginView"]; self.window.rootViewController = view; }
第二种用cookie
通过请求头可以传递一些web想要的一些信息,但是这个方法有些局限性,如果web跳转的时候头的信息会消失,最好的方法就是自定义cookie传值
NSURL * url = [NSURL URLWithString:self.url];
NSMutableURLRequset * request =[ [NSMutableURLRequest alloc]initWithURL:url];
NSString * body = [NSString stringWithFormat:@"uuid = %@&session=%@",uuid,sessionid];
[request setHttpBody:[body dataUsingEncoding:NSUTF8StringEncoding]];
[request setHttpMethod:@"POST"];
[self.myWebView loadRequest:request];
[self.view addSubview:self.myWebView];
//自定义cookie传值
//定义cookie 要设定的host
NSURL * url = [NSURL URLWithString:self.url];
NSURL * cookieHost = [NSURL URLWithString:self.url];
NSDictionary * dic = @{@"uuid":uuid,@"sessionid":sessionid,@"feedid":self.feedid,@"softversion":softversion,@"devicetype":deviceId,@"touuid": self.touuid};
[dic enumerateKeysAndObjectsUsingBlock:^(id key,id obj,BOOL * stop){
//设定cookie
NSHTTPCookie *cookie = [NSHTTPCookie cookieWithProperties:
[NSDictionary dictionaryWithObjectsAndKeys:
[cookieHost host], NSHTTPCookieDomain,
[cookieHost path], NSHTTPCookiePath,
key,NSHTTPCookieName,
obj,NSHTTPCookieValue,
nil]];
[[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:cookie];
}]
[self.myWebView loadRequset:request];//加载
[self.view addSubView:self.myWebView];
上面说的是web,下面说一下如何用AFNetworking发送post请求时怎么设置cookie吧
//获取cookie
NSArray *cookies = [NSHTTPCookie cookiesWithResponseHeaderFields:[response allHeaderFields] forURL:yourNSURL];
//以下代码进行请求,解析为cookie存入NSUserDefaults
[_manager post:URL parameters:nil success:^(AFHTTPRequestOperation * operation,id responseObject){
/*
从response的HeaderField获取头文件,从头文件中通过NSHTTPCookie的cookieWithResponseHeaderFields组成cookie的NSArray,将生成cookie的array,使用NSHttpCookie的requestHeaderFieldsWithCookies方法拼接成合法的http header field,最后set到request中即可。
*/
NSDictionary * fields = [operation.requset allHeaderFields];
NSArray * cookies = [NSHttpCookie cookiesWithResponseHeaderField:fields forURL:[NSURL URLWithString:BaseURLString]];
NSDictionary * requestFields = [NSHttpCookie requestHeaderFieldWithCookies:cookies];
[NSUserDefaluts standardUserDefaluts] setObject:[requestFields objectForKey:@"Cookie"] forked:mUserDefalutsCookie];
//使用jsonkit进行解析
int result = [self jsonTouserDefalut:ooperation];
}failure:^(AFHTTPRequestOperation * operation,NSError * error)
{
//使用B1的loginFailed方法
[_delelgate loginFailed];
} ];
在要使用时,从[NSUserDefaults standardUserDefaults]中取出,使用AFHTTPRequestOperationManager的[manager.requestSerializer setValue: forHTTPHeaderField:];对NSMutableRequest的headerField中的cookie进行赋值。
- AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
- manager.responseSerializer = [AFJSONResponseSerializer serializer];
- [manager.requestSerializer setValue: [[NSUserDefaults standardUserDefaults] objectForKey:mUserDefaultsCookie]forHTTPHeaderField:@"Cookie"];
- manager.responseSerializer.acceptableContentTypes=[NSSet setWithObject:@"text/html"];
- NSString* suffix=[NSString stringWithFormat:@"?m=user&a=edit&nickname=%@&age=%@",nickName,age];
- NSString* requestUrl =[BaseURLString stringByAppendingString:suffix];
- NSString* utf8=[requestUrl stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];//将请求地址转换为utf8编码,使用默认unicode进行请求会报编码错误
第三种就是用第三方授权登陆了,第三方开发文档上都写得很清楚,只要按照步骤一点一点来就行了