[iOS 開發(fā)]如何處理 iOS 原生網(wǎng)絡(luò)請求中的 cookie ?

時間:2016.12.26
背景:在 iOS 開發(fā)中硝皂,大部分應(yīng)用的用戶登錄機制都是基于 token 令牌的,我之前做過的項目也都是如此作谭,但是在我現(xiàn)在的新項目中稽物,由于服務(wù)端同學是沿用他們以前的 cookie 登錄機制,所以我也不得不換種方式來對(zhe)待(teng)登(yi)錄(xia)問題了折欠。

1.什么是 cookie贝或?cookie 和 token 有何區(qū)別?
cookie 是什么呢锐秦?cookie 在英語中通常是指餅干咪奖,當然,我這里指的不是农猬,而是 HTTP 網(wǎng)絡(luò)請求中用來記錄用戶信息的一種數(shù)據(jù)形式或者說一種機制。

cookie:在客戶端發(fā)送登錄操作的網(wǎng)絡(luò)請求時售淡,服務(wù)器在登陸成功返回的 response header 中會添加一個 set-cookie 的值斤葱,作為用戶的身份認證,如果是瀏覽器的話揖闸,后面每一次發(fā)請求時揍堕,瀏覽器都會自動將之前獲取到的 cookie 值插入到 request header 的 cookie 字段中,而且 cookie 本身包括多個屬性汤纸,比如有效期 expires衩茸、域 domain等,因此采用 cookie 的登錄機制需要考慮到對 cookie 本身的管理贮泞。cookie 主要是在 web 領(lǐng)域使用楞慈。

token:相比 cookie幔烛,token 令牌的登錄機制要更輕,直觀的感受是囊蓝,登錄認證成功后饿悬,服務(wù)器返回 token 值,然后在請求的 url 中拼接一段 “token=%^&%#&%#&” 就完事了聚霜,至于什么跨域狡恬、安全策略什么的,根本沒他什么事蝎宇,客戶端管理 token 也非常簡單弟劲,只要看好這個字符串就行了,所以 token 一般在移動端用的比較多姥芥。當然兔乞,移動應(yīng)用中的 web view 還是要處理 cookie 的。

2.iOS 中的網(wǎng)絡(luò)請求中如何處理 cookie撇眯?
在開始處理 cookie 時报嵌,需要了解兩個類,NSHTTPCookie 和 NSHTTPCookieStorage熊榛,在用的時候要注意幾點:

  • 在請求時锚国,NSURLSession 和 NSURLConnection 會自動幫我們管理 cookie 的,但并不完善玄坦。AFNetworking 默認設(shè)置了 NSURLRequest 的 HTTPShouldHandleCookies 屬性為 YES血筑。
  • 如果服務(wù)器設(shè)置了 Cookie 失效時間 expiresDate,并且 sessionOnly 為 FALSE煎楣,Cookie 就會被持久化到文件中豺总,下次啟動app會自動加載沙盒中的 Cookies。如果 sessionOnly 為 TRUE 或者 expiresDate 為空择懂,則不會自動持久化到沙盒喻喳。
  • 手動設(shè)置的 Cookie 不會被 NSHTTPCookieStorage 自動持久化到沙盒。
  • 不能簡單地依賴 NSHTTPCookieStorage 的 setCookie: 方法來做 cookie 的存儲困曙,因為在執(zhí)行 setCookie:時表伦, cookie 并不是馬上就更新了。參考: NSHTTPCookieStorage state not saved on app exit. Any definitive knowledge/documentation out there?
  • cookie 的 httpOnly 屬性是用來設(shè)置 cookie 是否能通過 js 去訪問慷丽。默認情況下蹦哼,cookie不會帶httpOnly選項(即為空),所以默認情況下要糊,客戶端是可以通過 js 代碼去訪問(包括讀取纲熏、修改、刪除等)這個cookie的。當cookie帶 httpOnly 選項時局劲,客戶端則無法通過js代碼去訪問(包括讀取勺拣、修改、刪除等)這個cookie容握。參考:聊一聊 cookie宣脉。

下面切入正題吧,我是如何做的呢剔氏?
首先是登錄塑猖。登錄成功后,服務(wù)器在 HTTP response header 中的 set-cookie 字段中返回了 cookie 的值谈跛,我們可已通過多種方式獲取到我們想要的 cookie 值羊苟,我是采用了下面這種方式來讀取的,因為我們的服務(wù)器沒有設(shè)置 expireDate感憾,所以我就自己做持久化存儲了蜡励。

NSDictionary *headerFields = [(NSHTTPURLResponse *)response allHeaderFields];
    NSArray <NSHTTPCookie *> *cookies =[NSHTTPCookieStorage sharedHTTPCookieStorage].cookies;  // 只要服務(wù)器在請求返回時帶了 cookie,NSHTTPCookieStorage 就會自動幫我們管理 cookie
    DDLogDebug(@"\n shared cookies %@\n", cookies);
    
    for (NSHTTPCookie *aCookie in cookies) {
        if ([aCookie.name isEqualToString:@"BUA"]) {  // 獲取并保存用戶cookie
           [[NSUserDefaults standardUserDefaults] setObject:cookie.properties forKey:kYIDUserDefaultUserCookieKey]; // 自己做持久化存儲
            break;
        }
    }

然后是請求時添加 cookie 到 request header阻桅。實際上這一步系統(tǒng)(NSURLSession / NSURLConnection)已經(jīng)自動幫我們處理了凉倚,具體細節(jié)我也不太清楚。

還要考慮重啟應(yīng)用后的操作嫂沉,由于我們的服務(wù)器沒有設(shè)置 expireDate 以及上面提到的其他原因稽寒,在程序重啟時,NSHTTPCookieStorage 并不會保存上一次使用應(yīng)用時的 cookie趟章,所以我們需要在程序啟動時讀取自己保存的 cookie杏糙,同時更新 NSHTTPCookieStorage 的 cookie。

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { {
    NSDictionary *cookieProperties = [[NSUserDefaults standardUserDefaults] objectForKey:kYIDUserDefaultUserCookieKey];
    NSHTTPCookie *cookie = [NSHTTPCookie cookieWithProperties:cookieProperties];
    [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:cookie];

...
}

關(guān)于 cookie 的有效期處理蚓土,在使用 cookie 時需要自己判斷 cookie 是否過期宏侍,NSHTTPCookieStorage 是不會自動幫我們處理的,更何況我們自己還做了本地存儲蜀漆,所以我們在用到 cookie 時還需要檢查 cookie 是否過期谅河,如果過期了,就要廢棄掉失效的 cookie确丢。我是在用戶的登錄狀態(tài)方法中做的處理:

- (BOOL)isLoggedIn {
    
    if (![self.cookie yid_isNotExpired]) { // cookie 失效绷耍,自動退出登錄
        [self logout];  // 刪除用戶信息、cookie
    }
    
    return [self.cookie yid_isNotEmpty];
}

最后還要記得在退出登錄時也要刪除 cookie:

[[NSHTTPCookieStorage sharedHTTPCookieStorage] deleteCookie:[self userCookie]];
[[NSUserDefaults standardUserDefaults] removeObjectForKey:kYIDUserDefaultUserCookieKey];

3.iOS 中的原生網(wǎng)絡(luò)請求如何與 webView 實現(xiàn) cookie 共享蠕嫁?

  • UIWebView 是屬于 URL Loading System 的一部分锨天,所以系統(tǒng)會自動幫我們將 NSHTTPCookieStorage 中的 cookie 同步到 UIWebView 中去毯盈。

  • 由于 WKWebView 是獨立于 URL Loading System 之外的剃毒,所以 WKWebView 所有的 cookie 管理都需要開發(fā)者自己操作,具體方法可以參考 stackoverflow 上的解決方案:Can I set the cookies to be used by a WKWebView?,也有國內(nèi)開發(fā)者根據(jù)這個答案造了一個輪子 haifengkao/YWebView赘阀。

遺留問題:
1.服務(wù)器是在什么時候更新/生成cookie 益缠?
2.登陸成功后,系統(tǒng)是如何自動添加 cookie 到 request header 中去的基公?
3.服務(wù)器是怎么識別客戶端的 cookie 的幅慌?

參考資料

  1. Wikipedia - HTTP cookie:
    https://en.wikipedia.org/wiki/HTTP_cookie
  2. 聊一聊 cookie:
    https://segmentfault.com/a/1190000004556040
  3. NSHTTPCookieStorage 官方文檔:
    https://developer.apple.com/reference/foundation/nshttpcookiestorage
    中文版:http://www.reibang.com/p/b10652a1803e
  4. iOS平臺下cookie的使用:
    http://www.reibang.com/p/65094611980c
  5. iOS HTTP網(wǎng)絡(luò)請求Cookie的讀取與寫入(NSHTTPCookieStorage)
    http://www.skyfox.org/ios-url-request-cookie.html
  1. NSHTTPCookieStorage state not saved on app exit. Any definitive knowledge/documentation out there?
    http://stackoverflow.com/questions/5837702/nshttpcookiestorage-state-not-saved-on-app-exit-any-definitive-knowledge-docume
  2. app開發(fā)token、cookie的區(qū)別轰豆,賬號密碼加密又是如何保證安全胰伍?
    https://www.zhihu.com/question/39137156
  3. 為什么 APP 要用 token 而不用 session 認證?
    https://www.v2ex.com/t/148426
  4. How to manage sessions with AFNetworking?
    http://stackoverflow.com/questions/10984374/how-to-manage-sessions-with-afnetworking/11039784#11039784
  5. Persisting Cookies In An iOS Application?
    http://stackoverflow.com/questions/4597763/persisting-cookies-in-an-ios-application
  6. NSHTTPCookieStorage and Cookie Expiration Date
    http://stackoverflow.com/questions/7203641/nshttpcookiestorage-and-cookie-expiration-date/7209706#7209706
  7. Can I set the cookies to be used by a WKWebView?http://stackoverflow.com/questions/26573137/can-i-set-the-cookies-to-be-used-by-a-wkwebview
  8. haifengkao/YWebView:https://github.com/haifengkao/YWebView
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末酸休,一起剝皮案震驚了整個濱河市骂租,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌斑司,老刑警劉巖渗饮,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異宿刮,居然都是意外死亡互站,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進店門僵缺,熙熙樓的掌柜王于貴愁眉苦臉地迎上來胡桃,“玉大人,你說我怎么就攤上這事谤饭”贽啵” “怎么了?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵揉抵,是天一觀的道長亡容。 經(jīng)常有香客問我,道長冤今,這世上最難降的妖魔是什么闺兢? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮戏罢,結(jié)果婚禮上屋谭,老公的妹妹穿的比我還像新娘。我一直安慰自己龟糕,他們只是感情好桐磁,可當我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著讲岁,像睡著了一般我擂。 火紅的嫁衣襯著肌膚如雪衬以。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天校摩,我揣著相機與錄音看峻,去河邊找鬼。 笑死衙吩,一個胖子當著我的面吹牛互妓,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播坤塞,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼冯勉,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了摹芙?” 一聲冷哼從身側(cè)響起珠闰,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎瘫辩,沒想到半個月后伏嗜,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡伐厌,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年承绸,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片挣轨。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡军熏,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出卷扮,到底是詐尸還是另有隱情荡澎,我是刑警寧澤,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布晤锹,位于F島的核電站摩幔,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏鞭铆。R本人自食惡果不足惜或衡,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望车遂。 院中可真熱鬧封断,春花似錦、人聲如沸舶担。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽衣陶。三九已至柄瑰,卻和暖如春废岂,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背狱意。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留拯欧,地道東北人详囤。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像镐作,于是被迫代替她去往敵國和親藏姐。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,713評論 2 354

推薦閱讀更多精彩內(nèi)容