iOS設(shè)置自定義Cookie

當(dāng)訪問一個(gè)網(wǎng)頁的時(shí)候,NSURLRequest會(huì)默認(rèn)幫你主動(dòng)記錄當(dāng)前站點(diǎn)的設(shè)置的Cookie,然后訪問之后就會(huì)自動(dòng)寫入磁盤,iOS是把cookie信息放在的NSHTTPCookieStorage容器中管理,當(dāng)下一次請(qǐng)求的時(shí)候,NSURLRequest會(huì)從內(nèi)存中拿出上次保存下來的Cookie繼續(xù)去請(qǐng)求。

Cookie

Cookie有服務(wù)器端生成,響應(yīng)后發(fā)送給客戶端,每一個(gè)Cookie都是一個(gè)NSHTTPCookie類的實(shí)例。

NSHTTPCookieStorage

NSHTTPCookieStorage實(shí)現(xiàn)了一個(gè)管理cookie的單例對(duì)象(只有一個(gè)實(shí)例),每個(gè)Cookie都是NSHTTPCookie類的實(shí)例。同一個(gè)域下的Cookie在應(yīng)用內(nèi)是共享的。

HTTPHeader

HTTPHeader中包含HTTP請(qǐng)求和響應(yīng)的參數(shù),header中定義了傳輸數(shù)據(jù)的各種特性。header以屬性名開始,屬性值之間用;間隔 。Cookie屬于HTTPHeader的一部分。

iOS中Cookie的讀取和寫入

Cookie一般是通過http的Response中傳過來,作為Response的HTTP Header中,系統(tǒng)默認(rèn)會(huì)將cookie寫入磁盤保存。那么如何獲取Cookie,并且寫入自定義Cookie呢?

需要先手動(dòng)獲取當(dāng)前NSHTTPCookieStorage中的所有cookie,然后將cookie放到NSURLRequest請(qǐng)求頭中

1.獲取已有的Cookie,然后添加新的Cookie。

- (NSArray *)fetchNewCookies {
    NSMutableArray *cookies = [[[NSHTTPCookieStorage sharedHTTPCookieStorage] cookiesForURL:[NSURL URLWithString:@"https://backend.gmei.com"]] mutableCopy];
    NSHTTPCookie *accessCookie = [self fetchAccessTokenCookie];
    //添加新Cookie最好多加一步去重
    [cookies addObject:accessCookie];
    return [cookies copy];
}

- (NSHTTPCookie *)fetchAccessTokenCookie {
     NSMutableDictionary *properties = [NSMutableDictionary dictionary];
    [properties setObject:@"_gm_token" forKey:NSHTTPCookieName];
    [properties setObject:accessToken forKey:NSHTTPCookieValue];
    [properties setObject:@"backend.gmei.com" forKey:NSHTTPCookieDomain];
    [properties setObject:@"/" forKey:NSHTTPCookiePath];
    NSHTTPCookie *accessCookie = [[NSHTTPCookie alloc] initWithProperties:properties];
    return accessCookie;
}

iOS中NSHTTPCookie有一系列的鍵值對(duì)作為Cookie的屬性
HTTPCookie屬性中的key有:

NSString *NSHTTPCookieComment;
NSString *NSHTTPCookieCommentURL;
NSString *NSHTTPCookieDiscard;
NSString *NSHTTPCookieDomain;
NSString *NSHTTPCookieExpires;
NSString *NSHTTPCookieMaximumAge;
NSString *NSHTTPCookieName;
NSString *NSHTTPCookieOriginURL;
NSString *NSHTTPCookiePath;
NSString *NSHTTPCookiePort;
NSString *NSHTTPCookieSecure;
NSString *NSHTTPCookieValue;
NSString *NSHTTPCookieVersion;

下面簡(jiǎn)單解釋下每個(gè)key的含義。

  • NSHTTPCookieComment
    包含cookie的注釋的NSString對(duì)象,注釋項(xiàng),用戶說明該 Cookie 有何用途,對(duì)Vesion1以及以后的版本有效,是可選屬性

  • NSHTTPCookieCommentURL
    包含cookie的CommentURL的NSURL/NSString對(duì)象,對(duì)Vesion1以及以后的版本有效,是可選屬性。

  • NSHTTPCookieDiscard
    一個(gè)NSString對(duì)象,用于標(biāo)識(shí)在會(huì)話結(jié)束時(shí)是否應(yīng)該丟棄改Cookie,是可選屬性。String的值必須是True或者false。默認(rèn)值是false,除非該cookie是version1或更高版本,否則不指定NSHTTPCookieMaximumAge的值,在這種情況下,它被假定為TRUE

  • NSHTTPCookieDomain
    包含cookie的域的NSString對(duì)象,如果缺少此cookie屬性,則會(huì)根據(jù)NSHTTPCookieOriginURL的值推斷該域。如果未指定NSHTTPCookieOriginURL的值,則必須為NSHTTPCookieDomain指定值。

  • NSHTTPCookieExpires
    指定了Cookie過期日期的NSDate對(duì)象或NSString對(duì)象,此cookie屬性僅用于版本0的Cookie,是可選屬性

  • NSHTTPCookieMaximumAge
    個(gè)包含一個(gè)整數(shù)值的NSString對(duì)象,表示cookie最大失效時(shí)間。僅適用于版本1 Cookie及更高版本。默認(rèn)值為“0”。此cookie屬性是可選的。

  • NSHTTPCookieName
    包含cookie名稱的NSString對(duì)象。此cookie屬性是必選的。

  • NSHTTPCookieValue
    包含cookie的值的NSString對(duì)象。此cookie屬性是必選的。

  • NSHTTPCookieOriginURL
    包含設(shè)置此cookie的URL的NSURL或NSString對(duì)象。如果您不提供NSHTTPCookieOriginURL的值,則必須為NSHTTPCookieDomain提供一個(gè)值。

  • NSHTTPCookiePath
    該Cookie是在當(dāng)前的哪個(gè)路徑下生成的,/表示在當(dāng)前目錄,此cookie屬性是必選的。

  • NSHTTPCookiePort
    NSString對(duì)象,包含逗號(hào)分隔的整數(shù)值,指定Cookie的端口。僅適用于version1或更高版本。默認(rèn)值為空字符串,是可選的。

  • NSHTTPCookieSecure
    一個(gè)NSString對(duì)象,如果設(shè)置了這個(gè)屬性,那么只會(huì)在 SSH 連接時(shí)才會(huì)回傳該 Cookie。默認(rèn)是fasle

  • NSHTTPCookieVersion
    Cookie有兩個(gè)版本:Version 0 和 Version 1。通過它們有兩種設(shè)置響應(yīng)頭的標(biāo)識(shí),分別是 “Set-Cookie”和“Set-Cookie2”。該屬性的值必須是“0”或“1”。默認(rèn)值為“0”,是可選的。

2.Cookie的本地同步和動(dòng)態(tài)綁定

1的操作首先是構(gòu)造需要寫入的自定義Cookie,構(gòu)造成功后,因?yàn)镽esponse中的Cookie不僅僅只有一個(gè),所以我們通過url獲取到當(dāng)前域下的Cookie得到的是一個(gè)數(shù)組Cookies,然后將自定義的Cookie添加到原有的Cookies數(shù)組中得到新的Cookies。

NSMutableArray *cookies = [[[NSHTTPCookieStorage sharedHTTPCookieStorage] cookiesForURL:[NSURL URLWithString:@"https://backend.gmei.com"]] mutableCopy];

Okay,現(xiàn)在新Cookies我們已經(jīng)構(gòu)造好了。需要做的是,再新的http請(qǐng)求到來的時(shí)候,新的http請(qǐng)求的頭部中的Cookies是我們構(gòu)造好的Cookie。

  • 場(chǎng)景1 自定義的Cookie的value是常量

如果我們僅僅寫入的一個(gè)Cookie值是一個(gè)常量(當(dāng)然很少見),我們可以直接將新的Cookies交由NSHTTPCookieStorage管理,執(zhí)行完這段代碼后,之后的請(qǐng)求Header中的Cookies就是新的Cookies。如果fetchAccessTokenCookie方法中設(shè)置一個(gè)例如24小時(shí)的過期時(shí)間的key,那么24小時(shí)內(nèi),新的Cookies在客戶端都是有效的。

統(tǒng)提供setCookie方法,需要注意的是如果兩個(gè)cookie的name名字相同,后面的會(huì)覆蓋已經(jīng)存在的cookie。

/*!
    @method setCookie:
    @abstract Set a cookie
    @discussion The cookie will override an existing cookie with the
    same name, domain and path, if any.
*/
[- (void)setCookie:(NSHTTPCookie *)cookie;]

執(zhí)行就okay了

 NSHTTPCookie *accessCookie =  [self fetchAccessTokenCookie];
[[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:accessCookie];
  • 場(chǎng)景2 自定義的Cookie的value是變量且要求立即生效,不能遺漏任何一個(gè)http請(qǐng)求。

在這種要求生效的及時(shí)性和完整性的時(shí)候,上面的方案1就無法滿足。這個(gè)時(shí)候我們需要將新的Cookies和接下來的請(qǐng)求url進(jìn)行綁定。Cookie是HTTPHeader的一部分,所以現(xiàn)將得到的新Cookies,生成一個(gè)HTTPHeader,系統(tǒng)提供了將 cookie轉(zhuǎn)成請(qǐng)求頭的方法。

requestHeaderFieldsWithCookies:

UIWebView

NSHTTPCookie *accessCookie =  [self fetchAccessTokenCookie];
NSDictionary *requestHeaders = [NSHTTPCookie requestHeaderFieldsWithCookies:accessCookie];
[request setValue:[requestHeaders objectForKey:@"Cookie"] forHTTPHeaderField:@"Cookie"];
[_webView loadRequest:request];

AFNetworking

GET/PSOT/DELETE/PUT/PATCH

AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.requestSerializer.HTTPShouldHandleCookies = YES;            
[manager.requestSerializer setValue:newCookies forHTTPHeaderField:@"Cookie"];

對(duì)于上傳音視頻的時(shí)候,AFNetworking用的是AFURLSessionManager而不是AFHTTPRequestOperationManager。

NSMutableURLRequest *request = [[AFHTTPRequestSerializer serializer] multipartFormRequestWithMethod:@"POST" URLString:URLString parameters:parameters constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
        //沒有指定name的時(shí)候,name不能為空,默認(rèn)填充 @"file" 即可
        [formData appendPartWithFileData:data name:name fileName:fileName mimeType:mineType];
    } error:nil];
    request.timeoutInterval = 30;
    NSHTTPCookie *accessCookie =  [self fetchAccessTokenCookie];
NSDictionary *requestHeaders = [NSHTTPCookie requestHeaderFieldsWithCookies:accessCookie];
    [request setValue:[httpHeader objectForKey:@"Cookie"] forHTTPHeaderField:@"Cookie"];
    AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
    [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
    NSURLSessionUploadTask *uploadTask = [manager uploadTaskWithStreamedRequest:request progress:NULL completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {
        [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
        if (error) {
            [self failureWithTask:nil error:error failed:failed];
        } else {
            [self successWithTask:nil responseObject:responseObject success:success];
        }
    }];
    
    [uploadTask resume];

Alamofire

var cookies = HTTPCookieStorage.shared.cookies(for: URL(string: @"http://backend.gmei.com")
if let cookie = fetchAccessTokenCookie() {
   HTTPCookieStorage.shared.setCookie(cookie)
   HTTPCookieStorage.shared.cookieAcceptPolicy = .always
   cookies?.append(cookie)
   let headers = HTTPCookie.requestHeaderFields(with: cookies!)
   let dataRequest = Alamofire.request(urlString, method: 
   method, parameters: parameters, encoding: 
   URLEncoding.default, headers: headers)
   dataRequest.validate(statusCode: 200..<400)
       .responseData { (response) in
       if let data = response.result.value, 
       response.result.isSuccess {
             
       } else {
            
       }
    }
} 
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • iOS App開發(fā)中的Cookie 一、何為Cookie Cookie是網(wǎng)站為了便是終端身份,保存在終端本地的用戶...
    o本是后山人o偶作前堂客o閱讀 3,977評(píng)論 1 8
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,618評(píng)論 19 139
  • HTTP cookie(也稱為web cookie,網(wǎng)絡(luò)cookie,瀏覽器cookie或者簡(jiǎn)稱cookie)是網(wǎng)...
    留七七閱讀 18,383評(píng)論 2 71
  • 項(xiàng)目中用到了本地登錄存儲(chǔ)cookie,再進(jìn)行webView請(qǐng)求時(shí)間帶上cookie的功能。不是很清晰邏輯,于是學(xué)習(xí)...
    小胡子杰克閱讀 3,177評(píng)論 2 12
  • 前言 關(guān)于UIWebView的介紹,相信看過上文的小伙伴們,已經(jīng)大概清楚了吧,如果有問題,歡迎提問。 本文是本系列...
    CoderLF閱讀 9,353評(píng)論 2 12

友情鏈接更多精彩內(nèi)容