SessionID的本质
一、客户端用cookie保存了sessionID
客户端用cookie保存了sessionID,当我们请求服务器的时候,会把这个sessionID一起发给服务器,服务器会到内存中搜索对应的sessionID,如果找到了对应的 sessionID,说明我们处于登录状态,有相应的权限;如果没有找到对应的sessionID,这说明:要么是我们把浏览器关掉了(后面会说明为什 么),要么session超时了(没有请求服务器超过20分钟),session被服务器清除了,则服务器会给你分配一个新的sessionID。你得重 新登录并把这个新的sessionID保存在cookie中。
在没有把浏览器关掉的时候(这个时候假如已经把sessionID保存在cookie中了)这个sessionID会一直保存在浏览器中,每次请求的时候都会把这个sessionID提交到服务器,所以服务器认为我们是登录的;当然,如果太长时间没有请求服务器,服务器会认为我们已经所以把浏览器关掉了,这个时候服务器会把该sessionID从内存中清除掉,这个时候如果我们再去请求服务器,sessionID已经不存在了,所以服务器并没有在内存中找到对应的 sessionID,所以会再产生一个新的sessionID,这个时候一般我们又要再登录一次。
二、客户端没有用cookie保存sessionID
这 个时候如果我们请求服务器,因为没有提交sessionID上来,服务器会认为你是一个全新的请求,服务器会给你分配一个新的sessionID,这就是 为什么我们每次打开一个新的浏览器的时候(无论之前我们有没有登录过)都会产生一个新的sessionID(或者是会让我们重新登录)。
当我们一旦把浏览器关掉后,再打开浏览器再请求该页面,它会让我们登录,这是为什么?我们明明已经登录了,而且还没有超时,sessionID肯定还在服 务器上的,为什么现在我们又要再一次登录呢?这是因为我们关掉浏览再请求的时候,我们提交的信息没有把刚才的sessionID一起提交到服务器,所以服 务器不知道我们是同一个人,所以这时服务器又为我们分配一个新的sessionID,打个比方:浏览器就好像一个要去银行开户的人,而服务器就好比银行, 这个要去银行开户的人这个时候显然没有帐号(sessionID),所以到银行后,银行工作人员问有没有帐号,他说没有,这个时候银行就会为他开通一个帐 号。所以可以这么说,每次打开一个新的浏览器去请求的一个页面的时候,服务器都会认为,这是一个新的请求,他为你分配一个新的sessionID。
三. 以上的俩点通俗点说就是:当你打开一个浏览器时登陆账号后就会把当前账号的sessionID保存到浏览器的cookies里面,当在有效时间内访问时就会把这个sessionID作为包头发送服务器,服务器就会认为是当前这个账号的。当你关闭浏览器时,再次打开或者访问其他的浏览器时,在访问登陆账号以后的网络请求时就会出现你未登陆或者没有权限(app-逻辑:登陆-进入app-访问app的请求)。当我们用x-code运用AFNetWorking编程时,并不会像网页浏览器一样保存sessionid,(当第一次把app运行在手机上时也就是下载后第一次打开,出现登陆界面进行登陆,然后进入app里,这时进行网络请求时都没有问题。当运行进入app后,再次运行x-code时,检测已经有了账号就进入app里,在进行网络访问时就会出现userid失效或者未登陆错误)那么该怎么办??
四.后来大神告诉我AFNetWorking里面有个AFHTTPSessionManager会自动保存用户访问的信息
大神告诉我照着下面这样做:
就是在AFNetWorking封装的HttpTool请求失败的方法里判断下 当[error.description containsString:@"status code: 200"]状态码为200是成功时让他在登陆一下,这样就重新获取了服务器发来新的sessionid最后让他在次调用当前的这个post请求,(又回到一开始的post请求)
五.后来后台在修改用户请求的方法里,添加的权限管理(发送修改的post请求里携带参数suerid)必须是当前账号才能修改当前账号的信息,避免黑客不登录或者登陆自己的账号修改别人的账号信息。这样上面大神指导的方法就不管用了,又出现一开始的提示没有登陆或者没有权限。就自己试试了把重新登陆请求放在HttpTool的success方法里,结果也不行,,,,
六.其实上面所有的问题都可以通过笨的方法:在appdelete里让他重新登陆一下(发送post的登陆请求,但是这个请求用户是看不到的,只是网络请求下),app总是从appdelegate开始运行。但是感觉这样并不是多好,每一次的app运行(是运行app,不是每一次网络请求额)都分配一个新的sessionID。
八.后来经过找资料
实际上AFNetworking中并没有专门针对cookie封装的代码,但是由于它底层使用的是NSURLRequest,所以可以通过NSHTTPCookieStorage来操作cookie,读取和保存cookie的代码如下:
1.就在登陆的界面里的登陆请求后调用
- (void)setcookies{
NSArray *cookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookiesForURL: [NSURL URLWithString:BASE_URL]];
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:cookies];
[[NSUserDefaults standardUserDefaults] setObject:data forKey:@"kUserDefaultsCookie"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
2.在appdelegate方法里调用:
- (void)getcookies{
NSArray * cookies = [NSKeyedUnarchiver unarchiveObjectWithData: [[NSUserDefaults standardUserDefaults] objectForKey:@"kUserDefaultsCookie"]];
NSHTTPCookieStorage * cookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
for (NSHTTPCookie * cookie in cookies){
[cookieStorage setCookie: cookie];
}
}
也就是第一次下载运行后出现登陆界面,登陆的请求方法后里调用setcookies,把当前的cookies里的sessionid写进沙河里,然后在以后任何网络请求之前调用取cookies方法,
这样就可以就解决sessionid的问题啦
亲们也可以看下别人的文档:http://www.jianshu.com/p/5f52d2c6be7b给AFN加点Cookie - 简书
http://blog.csdn.net/zhaoxy_thu心砚THU的专栏
- 博客频道 - CSDN.NET
最后附加:
session原理:
sessionid相当于一个验证码(但是可以重复使用),由服务器生成,半个小时没有使用就失效,使用就重置为半个小时有效期。
每个http请求都使用同一个sessionid就认为是在同一个session里面,否则就要重新登录并生成新的(失效或者根本没有传也要重新登录)。
代码写法:
1:http请求类发送登录请求时,成功后获取到sessionid存到硬盘(NSUserDefaults或者SQLite)和http请求类。
2:http请求类发送其他请求时,把sessionid附带着传给服务器。服务器返回未登录的话弹出登录界面。
3:退出app(未退出登录)后重进时从硬盘获取sessionid给http请求类,没有的话弹出登录界面。
好了cookies的sessionID的问题暂时告一段落!!!!