Android端實現(xiàn)Cookie機制

簡介

Session是服務端驗證客戶端身份的一種機制喂击。而Cookie是客戶端存儲的一種身份憑證屠列,由服務端在回應的消息頭中通過Set-Cookie字段“種”在客戶端萤厅。以后每次客戶端在向服務端請求時都會在消息頭中帶上Cookie字段入录。服務端就會根據(jù)Cookie的來判斷此次請求是從哪個用戶發(fā)過來的来涨,是否是一次有效請求等塔橡。有關Cookie的標準定義可以參考 RFC6265梅割。以下我們稍做介紹。

舉個例子

首次打開瀏覽器請求http://www.baidu.com 葛家,我們會得到一個response消息頭如下格式户辞。

首次請求百度返回的消息頭的一部分

可以看到里面包含了多條Set-Cookie,Cookie是key-value形式的癞谒。每條Cookie都有一個效信息字段底燎,有些還含有expires、domain和path等字段扯俱。其中的domain和path字段书蚪,區(qū)分了不同的cookie可以被哪些網(wǎng)頁鏈接獲得,如未設置domain迅栅,則使用當前的訪問鏈接替代殊校。比如上面的BD_HOME=0,我們在下表[本地cookie信息]中读存,一樣可以看到它的domain為www.baidu.com为流,這是因為我們訪問的就是這個地址呕屎。其中的expires和max-age定義了該Cookie的有效期,失效的Cookie在下次請求時不會被加入到Cookie頭中敬察。

請求后我們查看瀏覽器的Cookie表秀睛,可以看到這些Cookie信息被“種”下了。


本地cookie信息

此時再發(fā)送一條請求莲祸,可以看到請求的消息頭如下:


請求消息頭Cookie信息

不同網(wǎng)站的請求蹂安,會因為請求鏈接的不同,只能從瀏覽器取得屬于自己的cookie锐帜,根據(jù)上文提到的domain和path字段來區(qū)分田盈。關于匹配的詳細規(guī)則還是可以查看RFC6265掀虎。這邊我們用domain的匹配來稍微說下智政,在標準的5.1.3條目是有關domain matching的。

A string domain-matches a given domain string if at least one of the
   following conditions hold:

   o  The domain string and the string are identical.  (Note that both
      the domain string and the string will have been canonicalized to
      lower case at this point.)

   o  All of the following conditions hold:

      *  The domain string is a suffix of the string.

      *  The last character of the string that is not included in the
         domain string is a %x2E (".") character.

      *  The string is a host name (i.e., not an IP address).

從中我們可以看出domain要滿足兩點才能算是匹配射众,第一點蛮拔,完全相同述暂;如果第一點不滿足則需要,請求鏈接的后綴包含存儲的cookie的domain建炫,并且不包含部分的最后一個字符還得是"."畦韭,并且還是是個域名,而非IP地址踱卵。domain匹配成功后廊驼,還要匹配path据过,path的匹配要比domain復雜一些惋砂,具體可以查看標準的5.1.4。path匹配可以做到一個網(wǎng)站下的頁面可以分別存儲不同的cookie绳锅,也可以共享上層父頁面的cookie西饵,比較靈活。

客戶端實現(xiàn)

Android自身所帶的HttpUrlConnection方法是默認不開啟Cookie存儲的鳞芙。不過我們可以用java提供的幾個類來在Android中實現(xiàn):
可以先在所有請求之前聲明

CookieHandler.setDefault(new CookieManager(null, CookiePolicy.ACCEPT_ALL));

開啟此開關后眷柔,每次請求的Set-Cookie信息都會被CookieManager處理。CookieManager又會使用第一個參數(shù)傳入的CookieStore來處理Cookie的存儲問題原朝,因為此處傳入了null驯嘱,系統(tǒng)會默認調(diào)用一個基于CookieStore實現(xiàn)的CookieStoreImpl類來處理Cookie的存儲,這個類的只有基于內(nèi)存的存儲喳坠,當進程被殺死后鞠评,下次再進入應用,保存的Cookie信息就會丟失壕鹉。所以我們需要基于CookieStore這個接口實現(xiàn)一個具有內(nèi)存和本地雙存儲機制的Cookie存儲類剃幌。

可以參考:Fran Montiel實現(xiàn)的PersistentCookieStore 類:
https://gist.github.com/franmontiel/ed12a2295566b7076161

當解決了Cookie的存儲后聋涨,我們就需要考慮以后我們的每次請求需要在請求的消息頭中加入Cookie字段。以上用CookieStore存儲下來的Cookie信息都會被保存成HttpCookie形式的信息负乡。我們可以上面的百度例子中看到Cookie的組成樣式牍白,所以我們可以提取CookieStore中的信息并組合。

StringBuilder cookieBuilder = new StringBuilder();
String divider = "";
for (HttpCookie cookie : getCookies()) {
    cookieBuilder.append(divider);
    divider = ";";
    cookieBuilder.append(cookie.getName());
    cookieBuilder.append("=");
    cookieBuilder.append(cookie.getValue());
}
cookieString = cookieBuilder.toString();

然后把這個cookieString在以后的請求中加入到頭中抖棘,如果你用HttpUrlConnection茂腥,你就可以

setRequestProperty("Cookie",cookieString);  

如果你需要讓應用中打開的WebView頁面也能共享使用Cookie,則需要使用android.webkit.CookieManager類來設置切省,簡單式例代碼如下础芍。注意,第一個參數(shù)要使用鏈接的host部分数尿。這樣讓web端的不同頁面也可以共享這些cookie仑性。

for (HttpCookie cookie : getCookies()) {
    CookieManager.getInstance().setCookie(Uri.parse(url).getHost(), cookie.toString());
}

OK,大功告成右蹦。

以下是我在Github上開源的一個基于Volley實現(xiàn)的網(wǎng)絡層框架诊杆,也包括Cookie機制的Http請求,歡迎大家fork:
https://github.com/CPPAlien/DaVinci

作者簡介
彭濤(@彭濤me) 致力于讓技術變得易懂且有趣
個人博客:http://pengtao.me, GitHub地址:https://github.com/CPPAlien

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末何陆,一起剝皮案震驚了整個濱河市晨汹,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌贷盲,老刑警劉巖淘这,帶你破解...
    沈念sama閱讀 219,589評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異巩剖,居然都是意外死亡铝穷,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,615評論 3 396
  • 文/潘曉璐 我一進店門佳魔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來曙聂,“玉大人,你說我怎么就攤上這事鞠鲜∧梗” “怎么了?”我有些...
    開封第一講書人閱讀 165,933評論 0 356
  • 文/不壞的土叔 我叫張陵贤姆,是天一觀的道長榆苞。 經(jīng)常有香客問我,道長霞捡,這世上最難降的妖魔是什么坐漏? 我笑而不...
    開封第一講書人閱讀 58,976評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上仙畦,老公的妹妹穿的比我還像新娘输涕。我一直安慰自己,他們只是感情好慨畸,可當我...
    茶點故事閱讀 67,999評論 6 393
  • 文/花漫 我一把揭開白布莱坎。 她就那樣靜靜地躺著,像睡著了一般寸士。 火紅的嫁衣襯著肌膚如雪檐什。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,775評論 1 307
  • 那天弱卡,我揣著相機與錄音乃正,去河邊找鬼。 笑死婶博,一個胖子當著我的面吹牛瓮具,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播凡人,決...
    沈念sama閱讀 40,474評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼名党,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了挠轴?” 一聲冷哼從身側(cè)響起传睹,我...
    開封第一講書人閱讀 39,359評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎岸晦,沒想到半個月后欧啤,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,854評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡启上,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,007評論 3 338
  • 正文 我和宋清朗相戀三年邢隧,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片碧绞。...
    茶點故事閱讀 40,146評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡府框,死狀恐怖吱窝,靈堂內(nèi)的尸體忽然破棺而出讥邻,到底是詐尸還是另有隱情,我是刑警寧澤院峡,帶...
    沈念sama閱讀 35,826評論 5 346
  • 正文 年R本政府宣布兴使,位于F島的核電站,受9級特大地震影響照激,放射性物質(zhì)發(fā)生泄漏发魄。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,484評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望励幼。 院中可真熱鬧汰寓,春花似錦、人聲如沸苹粟。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,029評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽嵌削。三九已至毛好,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間苛秕,已是汗流浹背肌访。 一陣腳步聲響...
    開封第一講書人閱讀 33,153評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留艇劫,地道東北人吼驶。 一個月前我還...
    沈念sama閱讀 48,420評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像店煞,于是被迫代替她去往敵國和親旨剥。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,107評論 2 356

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