iOS中Cookies的手動管理(及AFNetworking中Cookies的使用)

一, 什么是Cookies?

Cookie 是由服務(wù)器保存在用戶瀏覽器(客戶端)上的一塊數(shù)據(jù),它可以包含有關(guān)用戶的信息,比如果登陸的狀態(tài),用戶標(biāo)識等。

HTTP Cookie(也叫Web cookie或者瀏覽器Cookie)是服務(wù)器發(fā)送到用戶瀏覽器并保存在瀏覽器上的一塊數(shù)據(jù),它會在瀏覽器下一次發(fā)起請求時被攜帶并發(fā)送到服務(wù)器上。比較經(jīng)典的,可以它用來確定兩次請求是否來自于同一個瀏覽器,從而能夠確認(rèn)和保持用戶的登錄狀態(tài)。Cookie的使用使得基于無狀態(tài)的HTTP協(xié)議上記錄穩(wěn)定的狀態(tài)信息成為了可能。

Cookie有什么作用?

主要用在以下三個方面:

  • 會話狀態(tài)管理(如用戶登錄狀態(tài)、購物車)

  • 個性化設(shè)置(如用戶自定義設(shè)置)

  • 瀏覽器行為跟蹤(如跟蹤分析用戶行為)

cookie的處理步驟

cookie 是 http 協(xié)議的一部分,它的處理分為如下幾步:

  • 服務(wù)器向客戶端發(fā)送 cookie。
    • 通常使用 HTTP 協(xié)議規(guī)定的 Set-Cookie 頭操作。
    • 規(guī)范規(guī)定 cookie 的格式為 name = value 格式,且必須包含這部分。
  • 瀏覽器將 cookie 保存。
  • 每次請求瀏覽器都會將 cookie 發(fā)向服務(wù)器。

其他可選的 cookie 參數(shù)會影響將 cookie 發(fā)送給服務(wù)器端的過程,主要有以下幾種:

  • path:表示 cookie 影響到的路徑,匹配該路徑才發(fā)送這個 cookie。
  • expires 和 maxAge:告訴瀏覽器這個 cookie 什么時候過期,expires 是 UTC 格式時間,maxAge 是 cookie 多久后過期的相對時間。當(dāng)不設(shè)置這兩個選項時,會產(chǎn)生 session cookie,session cookie 是 transient 的,當(dāng)用戶關(guān)閉瀏覽器時,就被清除。一般用來保存 session 的 session_id。
  • secure:當(dāng) secure 值為 true 時,cookie 在 HTTP 中是無效,在 HTTPS 中才有效。
  • httpOnly:瀏覽器不允許腳本操作 document.cookie 去更改 cookie。一般情況下都應(yīng)該設(shè)置這個為 true,這樣可以避免被 xss 攻擊拿到 cookie。

Cookies 長什么樣子?

當(dāng)服務(wù)器收到HTTP請求時,可以在響應(yīng)頭里面增加一個Set-Cookie頭部。瀏覽器收到響應(yīng)之后會取出Cookie信息并保存,之后對該服務(wù)器每一次請求中都通過Cookie請求頭部將Cookie信息發(fā)送給服務(wù)器。大概都長的都是這個格式:

Set-Cookie: <cookie名稱>=<cookie值>

所以一個簡單的 Cookie 像這樣:

Set-Cookie = JSESSIONID=B26C93E76786551423AEA6DC74DFE676; Path=/; 

也有像這樣子的(Expires 指定一個特定的過期時間):

Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT;

各瀏覽器 Cookie 的存放位置

可以在瀏覽器的偏好設(shè)置里面查看和管理Cookies

safari : ~/library/cookies

chrome : ~/Library/Application\ Support/Google/Chrome/Default/Cookies

Firefox : ~/Library/Application\ Support/Firefox/Profiles/q0aq3fau.default/cookies.sqlite

FirefoxCookies

參考資料

cookie 和 session

*嚴(yán)重推薦閱讀MDN對 HTTP cookies 的說明


二, 在iOS 中使用 Cookies

先看看Cookie有關(guān)的三個工具

  • NSHTTPCookieStorage

這個類就是一個單例,它的主要任務(wù)就是管理 Cookies, 增刪改查等各種

  • NSURLRequest

NSURLRequest是HTTP請求協(xié)議URL資源的消息對象Request。主要需要設(shè)置URL,可設(shè)置超時時間timeoutInterval,以及增加各種請求頭,比如:

{
    Accept = "application/octet-stream";
    "Content-TotalSize" = 1458598;
    "Content-TransferAct" = 0;
    "Content-TransferInfo" = "userid=646;pid=0;filename=IMG_4599.JPG;filemd5=cad853931741744be14b7a54bec2308e;";
    "Set-Cookie" = "JSESSIONID=B26C93E76786551423AEA6DC74DFE676; Path=/";
    "Content-TransferPos" = 0;
    "Content-Type" = "application/octet-stream";
}
這其中就有我們終端需要加服務(wù)的Cookie, 其中包含了SessionId
  • NSHTTPURLResponse

NSHTTPURLResponse 是HTTP協(xié)議請求URL資源的響應(yīng)消息對象。這個對象將HTTP協(xié)議的序列化了,可以很方便的獲得的狀態(tài)碼(statusCode),消息報頭(allHeaderFields)等信息,比如:

{
HTTP/1.1 200 OK //協(xié)議版本以及狀態(tài)碼
"Access-Control-Allow-Methods" = "POST,GET";
"Content-Language" = "zh-CN";
"Content-Type" = "text/json;charset=UTF-8";
Server = "nginx/1.11.8";
"Set-Cookie" = "JSESSIONID=B26C93E76786551423AEA6DC74DFE676; Path=/";
lastClient = iPhone;
lastIp = "192.168.4.121";
}
這其中就有服務(wù)器給我們的終端Cookie, 其中包含了SessionId

開始手動管理 Cookies

NSHTTPURLResponse 獲取服務(wù)器發(fā)給我們的 Cookie
    NSHTTPURLResponse* response = (NSHTTPURLResponse* )task.response;
    NSDictionary *allHeaderFieldsDic = response.allHeaderFields;
    NSString *setCookie = allHeaderFieldsDic[@"Set-Cookie"];
    if (setCookie != nil) {
         NSString *cookie = [[setCookie componentsSeparatedByString:@";"] objectAtIndex:0];
         NSLog(@"cookie : %@", cookie); // 這里可對cookie進行存儲
    }
NSHTTPCookieStorage 獲取想要Cookie
NSHTTPCookieStorage *storagedCookies = [NSHTTPCookieStorage sharedHTTPCookieStorage];
                     for (NSHTTPCookie *cookie in storagedCookies.cookies){
                         NSLog(@"cookie : %@", cookie);
                     }
清除Cookie
/**
 *  清除Cookie,如比在用戶重新登錄的時候需要用的著
 */

NSHTTPCookieStorage *cookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
    NSArray *_tmpArray = [NSArray arrayWithArray:[cookieStorage cookies]];
    for (id obj in _tmpArray) {
        [cookieStorage deleteCookie:obj];
    }
    

三, 使用 AFNetworking 時,對Cookies管理的示例

AFNetworking 3.0 默認(rèn)是保存cookies的。

AFHTTPSessionManagerrequestSerializer的屬性HTTPShouldHandleCookies默認(rèn)就是 YES

模擬登錄,保存cookie以及設(shè)置cookie:

NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
    AFHTTPSessionManager *httpManager = [[AFHTTPSessionManager alloc] initWithBaseURL:[NSURL URLWithString:@"hostURL"] sessionConfiguration:sessionConfiguration];
    AFHTTPRequestSerializer *requestSerialization = [AFHTTPRequestSerializer serializer];
    requestSerialization.timeoutInterval = 15;
    
    // 設(shè)置自動管理Cookies
    requestSerialization.HTTPShouldHandleCookies = YES;
    
    // 如果已有Cookie, 則把你的cookie符上
    NSString *cookie = [[NSUserDefaults standardUserDefaults] objectForKey:@"Set-Cookie"];
        if (cookie != nil) {
            [requestSerialization setValue:cookie forHTTPHeaderField:@"Set-Cookie"];
        }
    
    // 安全策略
    AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone];
    securityPolicy.allowInvalidCertificates = YES;
    securityPolicy.validatesDomainName = NO;
    
    [httpManager POST:@"logInURL"
           parameters:nil
             progress:NULL
              success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
                  if ([responseObject[@"status"] isEqualToString:@"SUCCESS"]) {
                      //獲取 Cookie
                      NSHTTPURLResponse* response = (NSHTTPURLResponse* )task.response;
                      NSDictionary *allHeaderFieldsDic = response.allHeaderFields;
                      NSString *setCookie = allHeaderFieldsDic[@"Set-Cookie"];
                      if (setCookie != nil) {
                          NSString *cookie = [[setCookie componentsSeparatedByString:@";"] objectAtIndex:0];
                          // 這里對cookie進行存儲
                          [[NSUserDefaults standardUserDefaults] setObject:cookie forKey:@"cookie"];
                      }
                  }else{
                      // 登錄失敗
                  }
              }
              failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
                  NSString *errorMessage = error.userInfo[@"NSLocalizedDescription"];
              }];
              
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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

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