故事背景:新入職一家公司,做登錄系統(tǒng)涌哲,登錄api沒有提供usrid參數(shù)尚镰,只post用戶名和密碼狗唉,即可登錄成功分俯。然后調(diào)用退出登錄接口的時候饮戳,沒有任何參數(shù)橄登,直接get請求,一直都顯示“用戶未登錄”谣妻,問后臺蹋半,退登沒有參數(shù)减江,怎么確定是我這個用戶在退登呢,他告訴我一個名為session的東西份企,隨手百度一發(fā)巡莹,感覺打開了新世界的大門降宅。
1.什么是session
簡單講,就是服務(wù)器用于記錄用戶狀態(tài)的激才。
當(dāng)我們第一次請求時服務(wù)器會吧session信息反饋到客戶端贸营。之后每一次請求,客戶端再把session放到cookie中發(fā)送給服務(wù)端,服務(wù)端就知道是哪一個用戶在進(jìn)行操作了捕儒。
2.登錄請求,記錄session
NSString *userName =@“xxx”刘莹;
NSString *passWord =@“xxx”点弯;
NSString *str = @“http://……”;
NSDictionary *dic = @{@"username":userName,@"password":passWord};
AFHTTPSessionManager *manager=[AFHTTPSessionManager manager];
manager.responseSerializer.acceptableContentTypes=[NSSet setWithObjects:@"application/json", nil];
/*這句很重要矿咕,下面講*/
[manager.requestSerializer setHTTPShouldHandleCookies:NO]抢肛;
manager.requestSerializer.timeoutInterval=5.0f;
[manager POST:str parameters:dic success:^(NSURLSessionDataTask *task, id responseObject) {
//@“9”為后臺登錄成功返回到狀態(tài)碼
NSDictionary *dict = (NSDictionary *)responseObject;
NSString *status = dict[@"status"];
if([status isEqualToString:@"9"])
{
// —————————— 獲得session的cookie
NSHTTPURLResponse* response = (NSHTTPURLResponse* )task.response;
NSString* dataCookie = [NSString stringWithFormat:@"%@",[[response.allHeaderFields[@"Set-Cookie"]componentsSeparatedByString:@";"]objectAtIndex:0]];
if ([dataCookie isEqualToString:@"(null)"] || dataCookie == NULL) {
}else
{
[[NSUserDefaults standardUserDefaults] setObject:dataCookie forKey:@"cookie"];
}
// —————————— end
}
} failure:^(NSURLSessionDataTask *task, NSError *error) {
}];
}
以上是整個登錄請求的代碼,完成兩件事:1.把用戶賬號密碼post給服務(wù)器請求登錄 碳柱;2.登錄成功把從服務(wù)器返回的cookie(其中保存了用戶的session信息)記錄下來捡絮,為以后請求服務(wù)。
具體的解析如下:
使用AFHTTPSessionManager來請求莲镣,post后成功塊中會返回一個task數(shù)據(jù)福稳。
[response.allHeaderFields[@"Set-Cookie"]
首次登錄請求時,從請求頭中可以獲得服務(wù)器返回的cookie瑞侮。
3.其他涉及用戶的請求(以退登為例)的圆,在請求頭重添加session
NSString *str = @“http://……”鼓拧;
AFHTTPSessionManager *manager=[AFHTTPSessionManager manager];
manager.responseSerializer.acceptableContentTypes=[NSSet setWithObjects:@"application/json", nil];
manager.requestSerializer.timeoutInterval=5.0f;
/*在請求頭中添加cookie*/
NSString* headerCookie = [[NSUserDefaults standardUserDefaults] objectForKey:@"cookie"];
if(headerCookie!=nil&& headerCookie.length>0) {
[manager.requestSerializer setValue:headerCookie forHTTPHeaderField:@"Cookie"];
}
/*end*/
[manager GET:str parameters:nil success:^(NSURLSessionDataTask *task, id responseObject) {
NSDictionary *dict = (NSDictionary *)responseObject;
NSString *status = dict[@"status"];
NSString *message = dict[@"message"];
if ([status isEqualToString:@"0"]) {
//退登成功
[self logoutInLocal];
}
else
{
UIAlertView *alert=[[UIAlertView alloc]initWithTitle:@"提示" message:message delegate:self cancelButtonTitle:@"確定" otherButtonTitles:nil];
[alert show];
}
} failure:^(NSURLSessionDataTask *task, NSError *error) {
}];
之后的每次請求時,如上把session放到請求頭里毁枯,服務(wù)端就可以識別用戶了。
4.問題:
如上還是會產(chǎn)生一些問題:
1.當(dāng)用戶退登后赂韵,再次請求登錄,無法返回session质涛。
這個問題是因?yàn)檎贝瑂ession數(shù)據(jù)只會在第一次請求時返回,AFN會自動記錄headercookie酪耕,如果應(yīng)用沒有完全后臺退出,再次訪問登錄,不會有數(shù)據(jù)從請求頭返回過來。
這個時候只要加上
[manager.requestSerializer setHTTPShouldHandleCookies:NO]谷炸;
這句代碼即可。
2.當(dāng)用戶退出app后驶睦,再次進(jìn)入app溉痢,如果app前端處理過記住登錄狀態(tài)的話孩饼,要再向服務(wù)器請求一次登錄此迅,保證前后端一致。
在appdelegate中的didbecameactive方法中加入請求登錄方法即可坎怪。
(有什么不對的地方隙券,還請大神們以和緩的語氣指正)