cookie 和session

来源:互联网 发布:win7网络上有红叉 编辑:程序博客网 时间:2024/06/05 20:29


(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就消失的一干二净了

会查看cookie了,也会清空cookie了,怎么设置指定的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>

其实ios的cookie就这么简单。如果mac也支持这么干的话,那以后写点登陆的脚本不是简单多了:)




下面我们通过一个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 sharedHTTPCookieStoragesetCookie: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进行赋值。


  1. AFHTTPRequestOperationManager *manager           = [AFHTTPRequestOperationManager manager];  
  2.    manager.responseSerializer                       = [AFJSONResponseSerializer serializer];  
  3.      [manager.requestSerializer setValue: [[NSUserDefaults standardUserDefaults] objectForKey:mUserDefaultsCookie]forHTTPHeaderField:@"Cookie"];  
  4.    manager.responseSerializer.acceptableContentTypes=[NSSet setWithObject:@"text/html"];  
  5.    NSString* suffix=[NSString stringWithFormat:@"?m=user&a=edit&nickname=%@&age=%@",nickName,age];  
  6.    NSString* requestUrl                             =[BaseURLString stringByAppendingString:suffix];  
  7.   
  8.    NSString* utf8=[requestUrl stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];//将请求地址转换为utf8编码,使用默认unicode进行请求会报编码错误  



第三种就是用第三方授权登陆了,第三方开发文档上都写得很清楚,只要按照步骤一点一点来就行了



0 0
原创粉丝点击