iOS App开发中的Cookie
一、何为Cookie
Cookie是网站为了便是终端身份,保存在终端本地的用户凭证信息。Cookie中的字段与意义由服务端进行定义。例如,当用户在某个网站进行了登录操作后,服务端会将Cookie信息返回给终端,终端会将这些信息进行保存,在下一次再次访问这个网站时,终端会将保存的Cookie信息一并发送到服务端,服务端根据Cookie信息是否有效来判断此用户是否可以自动登录。
二、iOS中进行Cookie管理的两个类
iOS中进行HTTP网络请求Cookie管理主要由两个类负责,一个类是NSHTTPCookieStorage类,一个是NSHTTPCookie类。
1.NSHTTPCookieStorage
NSHTTPCookieStorage类采用单例的设计模式,其中管理着所有HTTP请求的Cookie信息,常用方法如下:
//获取单例对象
+ (NSHTTPCookieStorage *)sharedHTTPCookieStorage;
//所有Cookie数据数组 其中存放NSHTTPCookie对象
@property (nullable , readonly, copy) NSArray *cookies;
//手动设置一条Cookie数据
- (void)setCookie:(NSHTTPCookie *)cookie;
//删除某条Cookie信息
- (void)deleteCookie:(NSHTTPCookie *)cookie;
//删除某个时间后的所有Cookie信息 iOS8后可用
- (nullable NSArray *)cookiesForURL:(NSURL *)URL;
//获取某个特定URL的所有Cookie数据
- (void)removeCookiesSinceDate:(NSDate *)date NS_AVAILABLE(10_10, 8_0);
//为某个特定的URL设置Cookie
- (void)setCookies:(NSArray *)cookies forURL:(nullable NSURL *)URL mainDocumentURL:(nullable NSURL *)mainDocumentURL;
//Cookie数据的接收协议
/*
枚举如下:
typedef NS_ENUM(NSUInteger, NSHTTPCookieAcceptPolicy) {
NSHTTPCookieAcceptPolicyAlways,//接收所有Cookie信息
NSHTTPCookieAcceptPolicyNever,//不接收所有Cookie信息
NSHTTPCookieAcceptPolicyOnlyFromMainDocumentDomain//只接收主文档域的Cookie信息
};
*/
@property NSHTTPCookieAcceptPolicy cookieAcceptPolicy;
系统下面的两个通知与Cookie管理有关:
//Cookie数据的接收协议改变时发送的通知
FOUNDATION_EXPORT NSString * const NSHTTPCookieManagerAcceptPolicyChangedNotification;
//管理的Cookie数据发生变化时发送的通知
FOUNDATION_EXPORT NSString * const NSHTTPCookieManagerCookiesChangedNotification;
2.NSHTTPCookie
NSHTTPCookie是具体的HTTP请求Cookie数据对象,其中属性方法如下:
//下面两个方法用于对象的创建和初始化 都是通过字典进行键值设置
- (nullable instancetype)initWithProperties:(NSDictionary *)properties;
+ (nullable NSHTTPCookie *)cookieWithProperties:(NSDictionary *)properties;
//返回Cookie数据中可用于添加HTTP头字段的字典
+ (NSDictionary *)requestHeaderFieldsWithCookies:(NSArray *)cookies;
//从指定的响应头和URL地址中解析出Cookie数据
+ (NSArray *)cookiesWithResponseHeaderFields:(NSDictionary *)headerFields forURL:(NSURL *)URL;
//Cookie数据中的属性字典
@property (nullable, readonly, copy) NSDictionary *properties;
//请求响应的版本
@property (readonly) NSUInteger version;
//请求相应的名称
@property (readonly, copy) NSString *name;
//请求相应的值
@property (readonly, copy) NSString *value;
//过期时间
@property (nullable, readonly, copy) NSDate *expiresDate;
//请求的域名
@property (readonly, copy) NSString *domain;
//请求的路径
@property (readonly, copy) NSString *path;
//是否是安全传输
@property (readonly, getter=isSecure) BOOL secure;
//是否只发送HTTP的服务
@property (readonly, getter=isHTTPOnly) BOOL HTTPOnly;
//响应的文档
@property (nullable, readonly, copy) NSString *comment;
//相应的文档URL
@property (nullable, readonly, copy) NSURL *commentURL;
//服务端口列表
@property (nullable, readonly, copy) NSArray *portList;
三、清除Cookie
清除所有的cookie 方法:
NSURL *url = [NSURL URLWithString:@"http://www.baidu.com"];
if (url) {
NSArray *cookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookiesForURL:url];
for (int i = 0; i < [cookies count]; i++) {
NSHTTPCookie *cookie = (NSHTTPCookie *)[cookies objectAtIndex:i];
[[NSHTTPCookieStorage sharedHTTPCookieStorage] deleteCookie:cookie];
}
清除某一个特定的cookie方法:
NSArray * cookArray = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookiesForURL:[NSURL URLWithString:self.loadURL]]; NSString * successCode = @""; for (NSHTTPCookie*cookie in cookArray) { if ([cookie.name isEqualToString:@"cookiename"]) { [[NSHTTPCookieStorage sharedHTTPCookieStorage] deleteCookie:cookie]; } }
清除某一个url缓存的方法:
[[NSURLCache sharedURLCache] removeCachedResponseForRequest:[NSURLRequest requestWithURL:url]];
清除所有缓存方法:
[[NSURLCache sharedURLCache] removeAllCachedResponses];
引用或相关资料:
http://www.jb51.net/article/88173.htm
iOS关于Cookie验证登录状态
1、第一次进入应用,登录获取Cookie,此时如果用到的是AFN去获取接口数据,Cookie已经写入了,所以无需处理,每次请求的时候,会自动将该cookie传给后台去验证
2、将Cookie缓存到本地:
NSData *cookiesData = [NSKeyedArchiver archivedDataWithRootObject: [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies]];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject: cookiesData forKey:@"Cookie"];
[defaults synchronize];
3、当第二次进入应用的时候,先判断NSUserDefault是否有缓存的Cookie,如果有,需要将cookie写入,然后进入应用
NSArray *cookies = [NSKeyedUnarchiver unarchiveObjectWithData:[[NSUserDefaults standardUserDefaults] objectForKey:@"Cookie"]];
NSHTTPCookieStorage * cookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
for (NSHTTPCookie * cookie in cookies){
[cookieStorage setCookie: cookie];
}
4、当用户选择退出登录,需要清除缓存中的cookie,同时要将NSUserDefault中的Cookie删除
(1)清除请求头中的Cookie:
NSHTTPCookieStorage *manager = [NSHTTPCookieStorage sharedHTTPCookieStorage];
NSArray *cookieStorage = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies];
for (NSHTTPCookie *cookie in cookieStorage) {
[manager deleteCookie:cookie];
}
(2)清除NSUserDefault中的Cookie
[[NSUserDefaults standardUserDefaults] removeObjectForKey:@"Cookie"];
[defaults synchronize];
注意:关于Cookie还有有效期,就看后台怎么定义,前端只要判断是否过了有效期,如果过了有效期,如果过了有效期,就需要用户重新登录,反之则不需要
iOS UIWebView 通过 cookie 完成自动登录
1、相关介绍
iOS在UIWebView中获取的cookie的方法:NSHTTPCookieStorage* nCookies = [NSHTTPCookieStoragesharedHTTPCookieStorage];
再具体获取某个域的cookie:NSArray* cookiesURL = [nCookiescookiesForURL:[NSURLURLWithString:@"你的URL"]];
通过[[NSHTTPCookieStoragesharedHTTPCookieStorage]setCookie:userCookie]方法将cookies来保存起来,但是这样虽然可以保存cookies但是你应用退出之后还是会丢失(其实是cookies过期的问题),做好的方法是把cookies放到NSUserDefaults保存起来.
2、实现
1.在UIWebView的代理方法中实现获取cookies并将cookies放到NSUserDefaults保存起来:- (void)webViewDidFinishLoad:(UIWebView*)webView中写入
- (void)webViewDidFinishLoad:(UIWebView*)webView{
NSArray*nCookies = [[NSHTTPCookieStoragesharedHTTPCookieStorage]cookies];
for(NSHTTPCookie*cookieinnCookies){
if([cookieisKindOfClass:[NSHTTPCookieclass]]){
if([cookie.nameisEqualToString:@"PHPSESSID"]) {
NSNumber*sessionOnly =[NSNumbernumberWithBool:cookie.sessionOnly];
NSNumber*isSecure = [NSNumbernumberWithBool:cookie.isSecure];
NSArray*cookies = [NSArrayarrayWithObjects:cookie.name, cookie.value, sessionOnly, cookie.domain, cookie.path, isSecure,nil];
[[NSUserDefaultsstandardUserDefaults]setObject:cookiesforKey:@"cookies"];
break;
}
}
}
}
2.获取cookies:运行之后,UIWebView加载url之前获取保存好的cookies,并设置cookies,
NSArray*cookies =[[NSUserDefaultsstandardUserDefaults]objectForKey:@"cookies"];
if(cookies.count>0) {
NSMutableDictionary*cookieProperties = [NSMutableDictionarydictionary];
[cookiePropertiessetObject:[cookiesobjectAtIndex:0]forKey:NSHTTPCookieName];
[cookiePropertiessetObject:[cookiesobjectAtIndex:1]forKey:NSHTTPCookieValue];
[cookiePropertiessetObject:[cookiesobjectAtIndex:3]forKey:NSHTTPCookieDomain];
[cookiePropertiessetObject:[cookiesobjectAtIndex:4]forKey:NSHTTPCookiePath];
NSHTTPCookie*cookieuser = [NSHTTPCookiecookieWithProperties:cookieProperties];
[[NSHTTPCookieStoragesharedHTTPCookieStorage]setCookie:cookieuser];
}
注意:要在[self.webView loadRequest:req];之前设置获取cookies!
iOS AFNetworking中cookie重定向代码
// 1. 取出需要同步的url (登录请求中返回的重定向地址)
BESTHttpItem *httpItem = [BESTHttpHelper sharedHelper].curHttpItem;
NSString *url = [NSString stringWithFormat:@"%@/#/login", httpItem.frontend_addr];
// 2. 取出当前的headerFields
NSDictionary *headerFields = [NSHTTPCookie requestHeaderFieldsWithCookies:self.cookies];
// 3. 替换cookie地址
[NSHTTPCookie cookiesWithResponseHeaderFields:headerFields forURL:[NSURL URLWithString:url]];
ios 网络通信过程cookie的使用
今天做项目接口需要用到http通信传输将数据传存储到cookie进行通信,在网上找了一些方法,都是关于如何操作cookie的,明确指出如何将cookie配置到http请求体内的blog不多,现在说明如下:
在进行一个网络通信之后设备就会产生Cookie数据:
如果获取的Cookie为空,那么发起一个网络请求即可产生Cookie;
NSHTTPCookieStorage *cookieJar = [NSHTTPCookieStorage sharedHTTPCookieStorage];for(NSHTTPCookie *cookiein[cookieJar cookies]) { NSLog(@"%@", cookie);}
获取所有Cookie然后删除;
NSHTTPCookieStorage *cookieJar = [NSHTTPCookieStorage sharedHTTPCookieStorage];NSArray*_tmpArray = [NSArrayarrayWithArray:[cookieJar cookies]];for(idobj in _tmpArray) { [cookieJar deleteCookie:obj]; }
设置指定的Cookie,这样做只会设置Cookie到系统,在进行网络请求的时候并不会带着Cookie到服务端,这是很多blog未提及的;
NSMutableDictionary *cookieProperties = [NSMutableDictionary dictionary]; [cookiePropertiessetObject:@"username"forKey:NSHTTPCookieName]; [cookiePropertiessetObject:@"password"forKey:NSHTTPCookieValue]; [cookiePropertiessetObject:@"io"forKey:NSHTTPCookieDomain]; [cookiePropertiessetObject:@"com"forKey:NSHTTPCookieOriginURL]; [cookiePropertiessetObject:@"/"forKey:NSHTTPCookiePath]; [cookiePropertiessetObject:@"0"forKey:NSHTTPCookieVersion]; NSHTTPCookie *cookie = [NSHTTPCookie cookieWithProperties:cookieProperties]; [[NSHTTPCookieStorage sharedHTTPCookieStorage]setCookie:cookie];
上面说了Cookie的一些操作,现在对如何在请求中带着cookie通信
1:苹果自带网络请求库携带cookie通信
//Cookie的基本设置 NSDictionary *properties = [[NSMutableDictionary alloc] init]; [propertiessetValue:cookieValueforKey:NSHTTPCookieValue]; [propertiessetValue:cookieKeyforKey:NSHTTPCookieName]; [propertiessetValue:@""forKey:NSHTTPCookieDomain]; [propertiessetValue:[NSDate dateWithTimeIntervalSinceNow:60*60]forKey:NSHTTPCookieExpires]; [propertiessetValue:@"/"forKey:NSHTTPCookiePath]; NSHTTPCookie *cookie = [[NSHTTPCookie alloc] initWithProperties:properties]; NSArray *cookies=[NSArray arrayWithObjects:cookie,nil]; NSDictionary *headers=[NSHTTPCookie requestHeaderFieldsWithCookies:cookies]; //将cookie塞进Request请求 NSURL *url = [NSURL URLWithString:pathStr]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; request.timeoutInterval = self.timeoutInterval; [requestsetValue:@"application/json"forHTTPHeaderField:@"Content-Type"]; [requestsetValue:[headers objectForKey:@"Cookie"]forHTTPHeaderField:@"Cookie"];
这样就可以把cookie带到服务端进行通信了;
2:AFN携带cookie通信
同样,关于AFN如何携带cookie进行通信,网上的一些资料说的不是很明确,现说明如下:
NSString*cookieValue = @"AQIC5wM2LY4SfcxpzbIz4Pm51J82O5VFMd50x_es65I1DNU.*AAJTSQACMDEAAlNLABM1NjQ2MDM4ODMzNDI0NDkxOTcy*,JSESSIONID=50B3DDCD8ADDA7ACB3E5C36EFD0BB62F";NSString*cookieKey = @"iPlanetDirectoryPro";//Cookie的基本设置NSDictionary*properties = [[NSMutableDictionaryalloc] init]; [properties setValue:cookieValue forKey:NSHTTPCookieValue]; [properties setValue:cookieKey forKey:NSHTTPCookieName]; [properties setValue:@""forKey:NSHTTPCookieDomain]; [properties setValue:[NSDatedateWithTimeIntervalSinceNow:60*60] forKey:NSHTTPCookieExpires]; [properties setValue:@"/"forKey:NSHTTPCookiePath]; NSHTTPCookie *cookie = [[NSHTTPCookie alloc] initWithProperties:properties];NSArray*cookies=[NSArrayarrayWithObjects:cookie,nil];NSDictionary*headers=[NSHTTPCookie requestHeaderFieldsWithCookies:cookies];NSMutableDictionary*dic = [NSMutableDictionarydictionary]; [dic setObject:tokenIdValue forKey:tokenIdKey]; AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];//将Cookie绑定request请求[manager.requestSerializersetValue:[headers objectForKey:@"Cookie"] forHTTPHeaderField:@"Cookie"]; [manager GET:urlString parameters:dic success:^(AFHTTPRequestOperation *operation,idresponseObject) { } failure:^(AFHTTPRequestOperation *operation,NSError*error) { }];
上述2种方式亲测可行;