Android中Cookie獲取、保存以及同步

1.先看一下Chrome中的Cookie信息

訪問首頁信息時:

1.第一次調用的Header信息
2.再次請求時Header信息

第一次請求時,服務器會在Response Header中帶過來一個Set-Cookie,內容為JSESSIONID=C3E668A891BA4E1C160C91A7EBEAA540.h2;
再次請求時,瀏覽器會在Requst Header中的Cookie將JSESSIONID帶上。

在瀏覽器中調用登錄接口時:

3.直接調用登錄接口
4.打開首頁后再調用登錄接口

2.項目中實際問題

例如在一個項目中,登錄界面為原生開發,而一些訂單預定處理頁面使用WebView嵌套Html5頁面。結合實際開發,主要碰到了兩個問題:
1.項目中使用的Volley作為網絡請求庫,默認 只能獲取的respone header中的各類的第一條數據,如圖3中,會有兩條Set-Cookie,而Volley默認只會拿到第一條Set-Cookie,也就是只能拿到JSESSIONID的值,不會拿到tocken的值;
2.默認情況下,每一次的原生接口調用就會產生新的JSESSIONID(因為默認請求中沒有同步cookie),調用登錄接口時如何同步最新的JSESSIONID?
3.WebView中Cookie同步機制

3.解決問題

問題1:可以有兩種解決方案
1.修改Volley源碼:Volley#toolbox#HurlStack.java#performRequest()

@Override
    public HttpResponse performRequest(Request<?> request, Map<String, String> additionalHeaders)
            throws IOException, AuthFailureError {
        String url = request.getUrl();
        HashMap<String, String> map = new HashMap<String, String>();
        map.putAll(request.getHeaders());
        map.putAll(additionalHeaders);
       ...
        URL parsedUrl = new URL(url);
        HttpURLConnection connection = openConnection(parsedUrl, request);
        for (String headerName : map.keySet()) {
            connection.addRequestProperty(headerName, map.get(headerName));
        }
      ...
        for (Entry<String, List<String>> header : connection.getHeaderFields().entrySet()) {
            if (header.getKey() != null) {
                /*看這里...默認只獲取index=0的值*/
                Header h = new BasicHeader(header.getKey(), header.getValue().get(0));
                response.addHeader(h);
            }
        }
        return response;
    }

2.在發送請求的時候帶上最新的JSESSIONID(請求頭里添加Cookie),volley設置請求頭,代碼如下:

 
@Override
    public Map<String, String> getHeaders() throws AuthFailureError {
        String cookie = CookieManager.getInstance().getCookie(Constant.BASE_URL);
        sendHeader.put("Cookie", cookie);
        if(sendHeader != null) {
            return sendHeader;
        }
        return super.getHeaders();
    }

問題2:在調用登錄接口時同步最新的JSESSIONID。最初的解決辦法:會在剛進入APP時主動調用某一個接口,獲取JSESSIONID,并做保存,在后續的請求上會一直使用這個JSESSIONID。這個辦法最初竟然可以順暢的使用,可是后續發現Cookie會 產生新的內容,比如說有的接口會更新tocken,每次就需要手動單獨去更新tocken,這樣做很不利于管理。
現在的做法是,在Volley解析數據的時候拿到Cookie(以"Set-Cookie"作為Key值),并將Cookie保存到CookieManager中,當然如果已經有保存的Cookie,在請求的時候也要帶上,這樣就做到了原生請求的時候Cookie的同步,然后在調用WebView時,只需要從CookieManager中同步即可。可以在Volley的Request中處理:JsonObjectRequest#parseNetworkResponse()


@Override
    protected Response<JSONObject> parseNetworkResponse(NetworkResponse response) {
        try {
            String jsonString =
                    new String(response.data, HttpHeaderParser.parseCharset(response.headers));
            mHeader = response.headers.toString();
            JSONObject jsonObject = new JSONObject(jsonString);

            for(Map.Entry<String,String> entry : response.headers.entrySet()) {
                if("Set-Cookie".equalsIgnoreCase(entry.getKey())) {      
                    //將cookie保存到CookieManager
                    CookieManager.getInstance().setCookie(Constant.BASE_URL, entry.getValue());
                    break;
                }
            }
            return Response.success(jsonObject,
                    HttpHeaderParser.parseCacheHeaders(response));

        } catch (UnsupportedEncodingException e) {
            return Response.error(new ParseError(e));
        } catch (JSONException je) {
            return Response.error(new ParseError(je));
        }
    }

3.WebView中的Cookie機制
WebView是基于webkit內核的UI控件,相當于一個瀏覽器客戶端。它會在本地維護每次會話的cookie(保存在data/data/package_name/app_WebView/Cookies.db)。
如圖:

Cookies.db

當WebView加載URL的時候,WebView會從本地讀取該URL對應的cookie,并攜帶該cookie與服務器進行通信。WebView通過android.webkit.CookieManager類來維護cookie。CookieManager是 WebView的cookie管理類。

之前同步cookie需要用到CookieSyncManager類,現在這個類已經被deprecated。如今WebView已經可以在需要的時候自動同步cookie了,所以不再需要創建CookieSyncManager類的對象來進行強制性的同步cookie了。現在只需要獲得 CookieManager的對象將cookie設置進去就可以了。

CookieManager的使用方法
1.setCookie(String url, String cookie)
2.getCookie(String url)

Cookies.db 表記錄

數據庫會根據name、host、path等生成一條記錄,也即是說在CookieManager#setCookie()中name、host和path一致會導致覆蓋原來的記錄。

ps:調用SetCookie()方法時,如果一條Set-Cookie中包含JSESSIONID和tocken,Cookies.db對應的表中會插入兩天記錄,name分別為JSESSIONID和tocken;如果以圖3為例,會有兩條Set-Cookie,如果按照順序把兩條拼接,在Cookies.db的表中只會插入一條name為JSESSIONID的記錄,這種時候可以調用兩次setCookie()方法。

Cookie相關的Http頭

有 兩個Http頭部和Cookie有關:Set-Cookie和Cookie。

Set-Cookie由服務器發送,它包含在響應請求的頭部中。它用于在客戶端創建一個Cookie
Cookie頭由客戶端發送,包含在HTTP請求的頭部中。注意,只有cookie的domain和path與請求的URL匹配才會發送這個cookie。
Set-Cookie響應頭的格式如下所示:

Set-Cookie: <name>=<value>[; <name>=<value>]...
   [; expires=<date>][; domain=<domain_name>]
   [; path=<some_path>][; secure][; httponly]

expires=<date>: 設置cookie的有效期,如果cookie超過date所表示的日期時,cookie將失效。
如果沒有設置這個選項,那么cookie將在瀏覽器關閉時失效。
secure : 表示cookie只能被發送到http服務器。
httponly : 表示cookie不能被客戶端腳本獲取到。

注:臨時cookie(沒有expires參數的cookie)不能帶有domain選項。
當客戶端發送一個http請求時,會將有效的cookie一起發送給服務器。
如果一個cookie的domain和path參數和URL匹配,那么這個cookie就是有效的。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,182評論 6 543
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,489評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,290評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,776評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,510評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,866評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,860評論 3 447
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,036評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,585評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,331評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,536評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,058評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,754評論 3 349
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,154評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,469評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,273評論 3 399
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,505評論 2 379

推薦閱讀更多精彩內容