欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

htttp网络请求cookie的读取与写入(NSHTTPCookieStorage)

程序员文章站 2024-03-20 14:16:22
...

 

一.Cookie

Cookie是在客户端存储服务器状态的一种机制,Web服务器可以通过Set-Cookie或者Set-Cookie2 HTTP头部设置Cookie。

Cookie可以分为两类,会话Cookie和持久Cookie,会话Cookie是临时Cookie,当前会话结束(浏览器退出)时Cookie会被删除。持久Cookie会存储在用户的硬盘上,浏览器退出,然后重新启动后Cookie仍然存在。会话Cookie和持久Cookie的区别在于过期时间,如果设置了Discard参数(Cookie 版本1)或者没有设置Expires(Cookie版本0)或Max-Age(Cookie版本1)设置过期时间,则此Cookie为会话Cookie

Cookie有两个版本,一个是版本0(Netscape Cookies)和版本1(RFC 2965),目前大多数服务器使用的Cookie 0。

二.NSHTTPCookie

在iOS中使用NSHTTPCookie类封装一条cookie,通过NSHTTPCookie的方法读取到cookie的通用属性。

可以通过手工赋值的方式创建Cookie,如
+ (id)cookieWithProperties:(NSDictionary *)properties;
- (id)initWithProperties:(NSDictionary *)properties;
也可以从Cookie中读取到所有属性。
- (NSDictionary *)properties;

使用NSHTTPCookie的类方法可以将NSHTTPCookie实例与HTTP cookie header相互转换.
根据NSHTTPCookie实例数组生成对应的HTTP cookie header
+ (NSDictionary *)requestHeaderFieldsWithCookies:(NSArray *)cookies;

从headerFileds中读取到Cookie相关内容,生成NSHTTPCookie实例对象数组。
+ (NSArray *)cookiesWithResponseHeaderFields:(NSDictionary *)headerFields forURL:(NSURL *)theURL;
该方法会忽略headerFileds中与cookie无关的字段,如果headerFileds中的cookie没有指定domain,则使用theURL的domain,如果没有指定path,则使用”/”.

除非NSURLRequest明确指定不使用cookie(HTTPShouldHandleCookies设为NO),否则URL loading system会自动为NSURLRequest发送合适的存储cookie。从NSURLResponse返回的cookie也会根据当前的cookie访问策略(cookie acceptance policy)接收到系统中。

应用如下

1.原生NSURLConnection写法

一.获取cookie
- (IBAction)cookieTouched:(id)sender {
    NSURL *url = [NSURL URLWithString:@"http://xxx.xxx"];
    NSURLRequest *request = [NSURLRequest requestWithURL:url]
                                             cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData
                                         timeoutInterval:3];
    NSOperationQueue *queue = [[NSOperationQueue alloc]init];
    [NSURLConnection sendAsynchronousRequest:request
                                       queue:queue
                           completionHandler:^(NSURLResponse *response, NSData *data, NSError *error){
                              
                               //转换NSURLResponse成为HTTPResponse
                               NSHTTPURLResponse *HTTPResponse = (NSHTTPURLResponse *)response;
                               //获取headerfields
                               NSDictionary *fields = [HTTPResponse allHeaderFields];//原生NSURLConnection写法
                               // NSDictionary *fields = [operation.response allHeaderFields]; //afnetworking写法
                               NSLog(@"fields = %@",[fields description]);
 
                               //获取cookie方法1
                               // NSArray *cookies = [NSHTTPCookie cookiesWithResponseHeaderFields:fields forURL:url];
							   //获取cookie方法2
                               //NSString *cookieString = [[HTTPResponse allHeaderFields] valueForKey:@"Set-Cookie"];
                               //获取cookie方法3
                               NSHTTPCookieStorage *cookieJar = [NSHTTPCookieStorage sharedHTTPCookieStorage];
                               for (NSHTTPCookie *cookie in [cookieJar cookies]) {
                                   NSLog(@"cookie%@", cookie);
                               }
                           }];
    
}

2.AFNetworking 写法

AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
    manager.responseSerializer = [AFCompoundResponseSerializer serializer];
    //demo中的api返回的是html数据,不是json
    [manager POST:@"http://xxx.xxx" parameters:nil progress:^(NSProgress * _Nonnull uploadProgress) {
        
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        NSLog(@"\n======================================\n");
        NSDictionary *fields = ((NSHTTPURLResponse*)task.response).allHeaderFields;
        NSLog(@"fields = %@",[fields description]);
        NSURL *url = [NSURL URLWithString:@"http://xxx.xxx"];
        NSLog(@"\n======================================\n");
        //获取cookie方法1
        NSArray *cookies = [NSHTTPCookie cookiesWithResponseHeaderFields:fields forURL:url];
        for (NSHTTPCookie *cookie in cookies) {
            NSLog(@"cookie,name:= %@,valuie = %@",cookie.name,cookie.value);
        }
        NSLog(@"\n======================================\n");
//        //获取cookie方法2
//        NSString *cookies2 = [((NSHTTPURLResponse*)task.response) valueForKey:@"Set-Cookie"];
//        NSLog(@"cookies2 = %@",[cookies2 description]);
 
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        
    }];

3.清空Cookie

NSHTTPCookieStorage *cookieJar = [NSHTTPCookieStorage sharedHTTPCookieStorage];
  NSArray *cookieArray = [NSArray arrayWithArray:[cookieJar cookies]];
  for (NSHTTPCookie *obj in cookieArray) {
    [cookieJar deleteCookie:obj];
  }

4.手动设置Cookie 手动设置的Cookie不会自动持久化到沙盒

//第一次请求手动设置个cookie
-(void)test1:(NSString*)urlString{
    NSURL *url = [NSURL URLWithString:@"http://xxx.xxx"];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    
    NSMutableDictionary *cookieProperties = [NSMutableDictionary dictionary];
    [cookieProperties setObject:@"username" forKey:NSHTTPCookieName];
    [cookieProperties setObject:@"my ios cookie" forKey:NSHTTPCookieValue];
    [cookieProperties setObject:@"dev.skyfox.org" forKey:NSHTTPCookieDomain];
    [cookieProperties setObject:@"dev.skyfox.org" forKey:NSHTTPCookieOriginURL];
    [cookieProperties setObject:@"/" forKey:NSHTTPCookiePath];
    [cookieProperties setObject:@"0" forKey:NSHTTPCookieVersion];
    [cookieProperties setObject:[NSDate dateWithTimeIntervalSinceNow:60*60] forKey:NSHTTPCookieExpires];//设置失效时间
    [cookieProperties setObject:@"0" forKey:NSHTTPCookieDiscard]; //设置sessionOnly
 
    NSHTTPCookie *cookie = [NSHTTPCookie cookieWithProperties:cookieProperties];
    [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:cookie];
    [self.myWebView loadRequest:request];
}
//第二次请求会自动带上Cookie
- (IBAction)test2:(id)sender {
    NSURL *url = [NSURL URLWithString:@"http://xxx.xxx"];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    [self.mywebview2 loadRequest:request];
}

//设置多个Cookie
NSArray * heardCookie = [NSHTTPCookie cookiesWithResponseHeaderFields:[NSDictionary
dictionaryWithObject:[[NSString alloc] 
initWithFormat:@"cookieName=%@", userstring] //这里的cookieName要后台给
forKey:@"Set-Cookie"] 
forURL:[NSURL URLWithString:@"http://"]];

[[NSHTTPCookieStorage sharedHTTPCookieStorage]setCookies:heardCookie forURL:[NSURL URLWithString:@"http://"] mainDocumentURL:nil];

//passwd
NSArray * heardCookie = [NSHTTPCookie cookiesWithResponseHeaderFields:[NSDictionary 
dictionaryWithObject:[[NSString alloc] 
initWithFormat:@"cookiePasswd =%@", passString] //cookiePasswd也是后台给
forKey:@"Set-Cookie"] 
forURL:[NSURL URLWithString:@"http://"]];

[[NSHTTPCookieStorage sharedHTTPCookieStorage]setCookies:heardCookie forURL:[NSURL URLWithString:@"http://"] mainDocumentURL:nil];

//另一种设置Cookie的方法
NSString* cookie = [[NSString alloc] initWithFormat:@"accessToken=%@;path=/;domain=%@;httponly", token, host];
NSArray *headeringCookie = [NSHTTPCookie
                                cookiesWithResponseHeaderFields:
                                @{
                                  @"Set-Cookie":cookie,
                                  }
                                forURL:[NSURL URLWithString:url]];
// 通过setCookies方法,完成设置,这样只要一访问URL为HOST的网页时,会自动附带上设置好的header
 [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookies:headeringCookie forURL:[NSURL URLWithString:url]
mainDocumentURL:nil];

通过NSHTTPCookieStorage可读取/修改cookie接收策略,默认为NSHTTPCookieAcceptPolicyAlways.

- (NSHTTPCookieAcceptPolicy)cookieAcceptPolicy;
- (void)setCookieAcceptPolicy:(NSHTTPCookieAcceptPolicy)aPolicy.

一共有三种cookie accept policy,

typedef enum {
   NSHTTPCookieAcceptPolicyAlways,
   NSHTTPCookieAcceptPolicyNever,
   NSHTTPCookieAcceptPolicyOnlyFromMainDocumentDomain
} NSHTTPCookieAcceptPolicy;
NSHTTPCookieAcceptPolicyAlways:接收所有cookie,默认策略.
NSHTTPCookieAcceptPolicyNever: 拒绝所有cookie
NSHTTPCookieAcceptPolicyOnlyFromMainDocumentDomain:只接收main document domain中的cookie.

三.相关通知

NSHTTPCookieManagerCookiesChangedNotification
当NSHTTPCookieStorage实例中的cookies变化时发出此通知。

NSHTTPCookieManagerAcceptPolicyChangedNotification
当NSHTTPCookieStorage实例的cookie acceptance policy变化时发出此通知。