今天无意间翻到了以前有关cookies的代码,就顺便整理了一下,和大家分享下。
Cookies简介
这里有比较详细的介绍,本文就不再赘述了。click me
在iOS当中需要注意以下几点:
- 不管是NSURLConnection还是UIWebView都会保留并传递服务端的cookie,就是说基本所有的网络请求都会使用cookie
- 多个应用之间默认不共享cookie
- 临时cookie在应用重启之后就会消失
- 持久cookie在应用或系统重启之后不会消失
- cookie不能跨域,像.baidu.com和image.baidu.com这种也是跨域
- WKWebView因为没有缓存,不能使用cookie,想要使用,需做特殊处理。
注:cookie不能跨域是通用的,在所有情况下都是这样,并非在iOS系统上如此。.baidu.com和image.baidu.com可以使用彼此的cookie是因为服务端做了特殊的处理。
Cookies操作
iOS系统当中的cookies由系统底层实现和使用,同时提供了NSHTTPCookieStorage
和NSHTTPCookie
来统一操作cookie。NSHTTPCookieStorage
是一个单例,我们所有的cookies都存放在这里,当我们发起网络请求时,系统会默认从NSHTTPCookieStorage
当中匹配相应cookie并带上去,所以我们只需要操作NSHTTPCookieStorage
即可。
以下是一些简单的使用
/**
* 获得url对应的cookie
*
* @param url url
*
* @return url对应的cookie
*/
- (NSArray *)getCookiesForUrl:(NSString *)url
{
NSHTTPCookieStorage *sharedHTTPCookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
if ([sharedHTTPCookieStorage cookieAcceptPolicy] != NSHTTPCookieAcceptPolicyAlways) {
[[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookieAcceptPolicy:NSHTTPCookieAcceptPolicyAlways];
}
NSArray *cookies = [sharedHTTPCookieStorage cookiesForURL:[NSURL URLWithString:url]];
return cookies;
}
/**
* 获取应用下所有的cookie
*
* @return 所有的cookie
*/
- (NSArray *)getAllCookies
{
NSHTTPCookieStorage *sharedHTTPCookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
if ([sharedHTTPCookieStorage cookieAcceptPolicy] != NSHTTPCookieAcceptPolicyAlways) {
[[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookieAcceptPolicy:NSHTTPCookieAcceptPolicyAlways];
}
return sharedHTTPCookieStorage.cookies;
}
/**
* 将cookie数组当中的cookie设置到cookie缓存中
*
* @param mArrCookie cookie数组
*/
- (void)setCookiesFromArr:(NSArray *)mArrCookie
{
if (mArrCookie != nil && [mArrCookie count]>0) {
NSHTTPCookieStorage *sharedHTTPCookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
for (NSHTTPCookie *cookie in mArrCookie) {
[sharedHTTPCookieStorage setCookie:cookie];
}
}
}
/**
* 为特殊的url设置cookie
*
* @param mArrCookie cookie数组
* @param url 地址,此处地址格式需为.baidu.com这样
*/
- (void)setCookie:(NSArray *)mArrCookie forUrl:(NSString *)url
{
if (mArrCookie != nil && [mArrCookie count]>0) {
NSHTTPCookieStorage *sharedHTTPCookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
for (NSHTTPCookie *cookie in mArrCookie) {
NSMutableDictionary *cookieDic = [NSMutableDictionary dictionaryWithDictionary:[cookie properties]];
[cookieDic setObject:url forKey:@"Domain"];
NSHTTPCookie *tempCookie = [NSHTTPCookie cookieWithProperties:cookieDic];
[sharedHTTPCookieStorage setCookie:tempCookie];
}
}
}
/**
获取特定url相应key的value值
@param key cookie的key值
@param url url,一个完整的url地址,例如https://www.baidu.com/
@return 当前url下cookie当中当前key对应的value值
*/
- (NSString *)cookieValueWithKey:(NSString *)key forUrl:(NSURL *)url
{
NSHTTPCookieStorage *sharedHTTPCookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
if ([sharedHTTPCookieStorage cookieAcceptPolicy] != NSHTTPCookieAcceptPolicyAlways) {
[[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookieAcceptPolicy:NSHTTPCookieAcceptPolicyAlways];
}
NSArray *cookies = [sharedHTTPCookieStorage cookiesForURL:url];
for (NSHTTPCookie *item in cookies) {
if ([[item name] isEqualToString:key]) {
return [NSString stringWithString:[[item value] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
}
}
return nil;
}
//以下是一些将cookies本地化的操作
- (void)saveCacheCookie:(id)sender {
NSArray *mArrCookie = [self getAllCookies];
NSData *cookieData = [NSKeyedArchiver archivedDataWithRootObject:mArrCookie];
[[NSUserDefaults standardUserDefaults] setObject:cookieData forKey:@"cookieData"];
}
- (void)unzipCookie:(id)sender {
NSData *cookieData = [[NSUserDefaults standardUserDefaults] objectForKey:@"cookieData"];
NSArray *mArrCookie = [NSKeyedUnarchiver unarchiveObjectWithData:cookieData];
[self setCookiesFromArr:mArrCookie];
}
跨域问题
针对跨域问题,可以在服务器和客户端分别做处理解决
服务器:在服务器返回cookie时同时将相关联的其他域的cookie返回
客户端:在每次请求完成后,对想跨域的域名进行设置,添加对应的cookie
推荐在服务器配置相关策略
WKWebView使用cookie
因为WKWebView没有缓存,不使用NSHTTPCookieStorage
,其cookie只存在内存当中,当前页面被释放其cookie也就消失了。因此WKWebView当中的请求不能使用其他请求的cookie,同时两个WKWebView页面也不共享cookie。
所以想要WKWebView使用其他请求的cookie或者前一个WKWebView页面的cookie需要在WKWebView加载前执行一段js代码,将cookie设置进去,而每次WKWebView请求之后获取cookie,将其保存起来。至于存在哪里,NSHTTPCookieStorage
和NSUserDefaults
都是不错的选择。