Java中session、cookie、token的區別

一.Cookie

1.什么是cookie?

Cookie 技術產生源于 HTTP 協議在互聯網上的急速發展。隨著互聯網時代的策馬奔騰,帶寬等限制不存在了,人們需要更復雜的互聯網交互活動,就必須同服務器保持活動狀態(簡稱:保活)。

Cookie 是在 HTTP 協議下,服務器或腳本可以維護客戶工作站上信息的一種方式。Cookie 是由 Web 服務器保存在用戶瀏覽器(客戶端)上的小文本文件,它可以包含有關用戶的信息。無論何時用戶鏈接到服務器,Web 站點都可以訪問 Cookie 信息.

2.cookie的起源

Cookie最早是網景公司的前雇員Lou Montulli在1993年3月的發明。

3.Cookie時效性

Cookie的默認時效為Session,也就是說瀏覽器關閉,Cookie會和session一起失效,但是Cookie的有效時間是可以設置的。

Cookie有一個屬性expires,設置其值為一個時間,那么當到達此時間后,此cookie失效。

實現如下:

//創建cookie實例。 
HttpCookie cookie = new HttpCookie("id","666"); 
//設置cookie的過期時間,一小時后過期,自動清除文件 
cookie.Expires = DateTime.Now.AddMonths(60);
//將創建的cookie文件輸入到瀏覽器端 
Response.Cookies.Add(cookie);
//讀取cookie文件中存儲的值 
Response.Write(Request.Cookies["id"].Value);

4.Cookie文件的刪除、銷毀

由于 Cookie 在用戶的計算機中,所以無法直接將其直接移除。所以我們用瀏覽器來刪除 Cookie。首先是創建一個與要刪除的 Cookie 同名的新 Cookie,將該 Cookie 的到期日期設置為早于當前日期的某個日期,當瀏覽器檢查 Cookie 的到期日期時,瀏覽器便會丟棄這個現已過期的 Cookie。

//cookie的銷毀,給他設置一個時間,他就被銷毀了
cookie.Expires = DateTime.Now.AddMonths(-60); 

5.Cookie使用限制

Cookie是HTTP頭中的一個字段,雖然HTTP本身對這個字段并沒有多少限制,但是Cookie最終還是存儲在瀏覽器里,所以不同的瀏覽器對Cookie的存儲都有一些限制,不同的瀏覽器對 Cookie 的處理不一致,使用時一定要考慮。
客戶端用戶如果設置禁止 Cookie,則 Cookie 不能建立。 并且在客戶端,一個瀏覽器能創建的 Cookie 數量根據瀏覽器的不同,其上限也不同。


image.png

6.執行流程:

1)、首先,客戶端會發送一個http請求到服務器端。

2)、服務器端接受客戶端請求后,發送一個http響應到客戶端,這個響應頭,其中就包含Set-Cookie頭部,瀏覽器保存Cookie。

3)、瀏覽器第二次訪問,將保存的cookie發給后臺,后臺識別并更新cookie,返回瀏覽器再次保存。

為了方便理解,可以先看下這張流程執行圖加深概念


image.png

那么,在瀏覽器上面的請求頭和Cookie在那?下圖給大家截取了其中一種。


image.png
上面我們都是在談瀏覽器上的Cookie,那么在Android開發中,我們該如何去管理和使用Cookie?

7.Okhttp框架(本文是基于Okhttp3.0版本以上)

Okhttp是一款相當經典的網絡框架,它的API可以通過OkhttpClient中的CookieJar或者攔截器去管理Cookie的。

我們在構建單例OkhttpClient的時候,設置cookiejar或者攔截器,然后具體的操作(保存Cookie,取Cookie),Okhttp框架就會幫我們自動管理Cookie。

如下圖:


image.png

這是其中一種通過集合的增查特性,就可以簡單有效的幫我們管理Cookie。但我們還是要通過源代碼去一探究竟。首先,CookieJar是一個接口。


image.png

英文注釋翻譯過來就是:

CookieJar這個接口為HTTP cookies提供了強大的支持和相關策略。

這種策略的實現作用會負責選擇接受和拒絕那些cookie。一個合理的策略是拒絕所有的cookie,盡管這樣會干擾需要cookie的基于會話的自身身份驗證方案。

作為Cookie的持久性,該接口的實現也必須要提供Cookie的存儲。一種簡單的實現可以將cookie存儲在內存中;復雜的系統可以使用文件系統用于保存已接受的cookie的數據庫。這里的鏈接https://tools.ietf.org/html/rfc6265 指定cookie存儲模型更新和過期的cookie的策略。

所以,Okhttp的源碼告知我們可以將cookie存儲在內存中;復雜的系統可以使用文件系統用于保存已接受的cookie的數據庫。因此,我們就可以通過Map去簡單的管理和使用。

繼續分析CookieJar接口里面的方法,依舊上源碼


image.png

里面有方法一個是saveFromResponse(HttpUrl url, List cookies)、loadForRequest(HttpUrl url)

saveFromResponse方法注釋:根據這個jar的方法,可以將cookie從一個HTTP響應保存到這里。如果有響應,此方法可能會引起第二次HTTP響應,包括一個追蹤。對于這個隱蔽的HTTP特性,這里的cookie只包含其追蹤的cookie。簡單點理解就是如果我們使用了這個方法,就會進行追蹤(也就是說客戶端請求成功以后,在響應頭里面存cookie)

loadForRequest方法注釋:將cookie從這個方法加載到一個HTTP請求到指定的url。但是這個方法從網絡上返回的結果可能是一個空集合。簡單的實現將返回的尚未過期的并且已接受的cookie去進行匹配。(也就是加載url的時候在請求頭帶上cookie)。


image.png

這樣,我們通過以上代碼就可以完成了Cookie的非持久化。

那么這個非持久化又是什么呢?

前面我們說了,Cookie是具有時效性的,所以,Cookie的管理又分為持久化Cookie和非持久化Cookie。
非持久化Cookie存儲在內存中,也就意味著,其生命周期基本和app保持一致,app關閉后,Cookie丟失,一般我們也不使用這種方式。
持久化Cookie則是存儲在本地磁盤中,app關閉后不丟失。
那么,如果我們要使用Cookie的持久化策略,大體上可以參照上面的非持久化策略,只是需要將存儲方式改一下即可:

1).通過響應攔截器從response取出cookie并保存到本地,通過請求攔截器從本地取出cookie并添加到請求中

2).自定義CookieJar,在saveFromResponse方法中保存cookie到本地,在loadForRequest方法從本地取出cookie。

那么在這里主要介紹如何通過Okhttp的攔截器去進行持久化cookie操作。


image.png

1).保存cookie攔截器


image.png

2).保存cookie攔截器

這個SaveCookiesInterceptor攔截器的實現,是首先從response獲取set-cookie字段的值,然后通過SharedPreferences保存在本地。


image.png

將Cookie添加到請求頭:
AddCookiesInterceptor請求攔截器,這個攔截的作用就是判斷如果該請求存在cookie,則為其添加到Header的Cookie中。

寫好這兩個攔截器之后,我們只需要將實例對象放進OkhttpClient里面即可快速的完成Cookie持久化操作。(這兩個攔截器在同步Cookie的時候也很好用)


image.png

Okhttp使用cookie攔截器

拓展:如何通過客戶端的cookie與H5上面的cookie進行同步,下面這篇文章很好:

客戶端與H5同步Cookie

二.Session

Session是一個會話,會話就是Session。Session是對于服務端來說的,Session是服務器和客戶端建立連接時添加的一個客戶端連接標志,最終在服務器軟件(Apache、Tomcat、JBoss)轉化為一個臨時的Cookie發送給客戶端,當客戶端第一次請求服務器時,會檢查是否攜帶了這個Session(臨時Cookie),如果沒有則會添加Session,如果有就拿出這個Session來做相關操作。

那么為什么會出現session會話,它出現的機理是什么?

我們都知道,用瀏覽器打開一個網頁,用到的是HTTP協議,了解計算機的應該都知道這個協議,它是無狀態的,什么是無狀態呢?就是說這一次請求和上一次請求是沒有任何關系的,互不認識的,沒有關聯的。但是這種無狀態的的好處是快速。所以就會帶來一個問題就是,我希望幾個請求的頁面要有關聯,比如:我在www.a.com/login里面登陸了,我在www.a.com/index 也希望是登陸狀態,但是,這是2個不同的頁面,也就是2個不同的HTTP請求,這2個HTTP請求是無狀態的,也就是無關聯的,所以無法單純的在index中讀取到它在login中已經登陸了!

那怎么辦呢?方法一是這2個頁面我都去登陸一遍吧,方法二是用笨方法這2個頁面都去查詢數據庫,如果有登陸狀態,就判斷是登陸的了。這種查詢數據庫的方案雖然可行,但是每次都要去查詢數據庫不是個事,會造成數據庫的壓力。 所以正是這種不方便之處,一個新的客戶端存儲數據方式出現了:cookie。

cookie是把少量的信息存儲在用戶自己的電腦上,它在一個域名下是一個全局的,只要設置它的存儲路徑在域名www.a.com下 ,那么當用戶用瀏覽器訪問時,就可以從這個域名的任意頁面讀取cookie中的信息。所以就很好的解決了我在www.a.com/login頁面登陸了,我也可以在www.a.com/index獲取到這個登陸信息了。同時又不用反復去查詢數據庫。 雖然這種方案很不錯,也很快速方便,但是由于cookie 是存在用戶端,而且它本身存儲的信息容量也有限,最關鍵是用戶可以是可見的,并可以隨意的修改,很不安全。那如何又要安全,又可以方便的全局讀取信息呢?于是,這個時候,一種新的存儲會話機制:session 誕生了。

Session 就是在一次會話中解決2次HTTP的請求的關聯,讓它們產生聯系,讓2兩個頁面都能讀取到找個這個全局的session信息。session信息存在于服務器端,所以也就很好的解決了安全問題。

每個Session 有一個唯一的Session id。 Session的超時也是由服務器來控制。我們一般都會把Session和Cookie放在一起來說,它們具體的區別和聯系這里我就不多說了,可以看上面。Cookie分為內存中Cookie(也可以說是進程中Cookie)和硬盤中Cookie。大部分的Session機制都使用進程中Cookie來保存Session id的,關閉瀏覽器后這個進程也就自動消失了,進程中的Cookie自然就消失了,那么Session id也跟著消失了,再次連接到服務器時也就無法找到原來的Session了。
也有使用硬盤中Cookie,比如說CSDN的“記住我一周”,或者我們的購物車信息可以在切換不同瀏覽器時依然可用。這就要用到我們上文提到的另一種Cookie了——硬盤中Cookie,這時Session id將長期保存在硬盤上的Cookie中,直到失效為止。

三.Token

token是用戶身份的驗證方式,我們通常叫它:令牌。
最簡單的token組成:
uid(用戶唯一的身份標識)
time(當前時間的時間戳)
sign(簽名,由token的前幾位+鹽以哈希算法壓縮成一定長的十六進制字符串,可以防止惡意第三方拼接token請求服務器)。
還可以把不變的參數也放進token,避免多次查庫。

應用場景:

1):當用戶首次登錄成功(注冊也是一種可以適用的場景)之后, 服務器端就會生成一個 token 值,這個值,會在服務器保存token值(保存在數據庫中),再將這個token值返回給客戶端.

2):客戶端拿到 token 值之后,進行本地保存。(SP存儲是大家能夠比較支持和易于理解操作的存儲)

3):當客戶端再次發送網絡請求(一般不是登錄請求)的時候,就會將這個 token 值附帶到參數中發送給服務器.

4):服務器接收到客戶端的請求之后,會取出token值與保存在本地(數據庫)中的token值做對比

對比一:如果兩個 token 值相同, 說明用戶登錄成功過!當前用戶處于登錄狀態!

對比二:如果沒有這個 token 值, 則說明沒有登錄成功.

對比三:如果 token 值不同: 說明原來的登錄信息已經失效,讓用戶重新登錄.

四.Cookie和Session的區別:

1、cookie數據存放在客戶的瀏覽器上,session數據放在服務器上。

2、cookie不是很安全,別人可以分析存放在本地的cookie并進行cookie欺騙,考慮到安全應當使用session。

3、session會在一定時間內保存在服務器上。當訪問增多,會比較占用你服務器的性能,考慮到減輕服務器性能方面,應當使用cookie。

4、單個cookie保存的數據不能超過4K,很多瀏覽器都限制一個站點最多保存20個cookie。

5、所以個人建議:

將登陸信息等重要信息存放為session

其他信息如果需要保留,可以放在cookie中

五.Token 和 Session 的區別:

session和 token并不矛盾,作為身份認證token安全性比session好,因為每個請求都有簽名還能防止監聽以及重放攻擊,而session就必須靠鏈路層來保障通訊安全了。如上所說,如果你需要實現有狀態的會話,仍然可以增加session來在服務器端保存一些狀態。

App通常用restful api跟server打交道。Rest是stateless的,也就是app不需要像browser那樣用cookie來保存session,因此用session token來標示自己就夠了,session/state由api server的邏輯處理。如果你的后端不是stateless的rest api,那么你可能需要在app里保存session.可以在app里嵌入webkit,用一個隱藏的browser來管理cookie session.

Session是一種HTTP存儲機制,目的是為無狀態的HTTP提供的持久機制。所謂Session認證只是簡單的把User信息存儲到Session里,因為SID的不可預測性,暫且認為是安全的。這是一種認證手段。而Token,如果指的是OAuth Token或類似的機制的話,提供的是 認證 和 授權 ,認證是針對用戶,授權是針對App。

其目的是讓 某App有權利訪問 某用戶 的信息。這里的Token是唯一的。不可以轉移到其它App上,也不可以轉到其它 用戶 上。轉過來說Session。Session只提供一種簡單的認證,即有此SID,即認為有此User的全部權利。是需要嚴格保密的,這個數據應該只保存在站方,不應該共享給其它網站或者第三方App。所以簡單來說,如果你的用戶數據可能需要和第三方共享,或者允許第三方調用API接口,用Token。如果永遠只是自己的網站,自己的App,用什么就無所謂了。

token就是令牌,比如你授權(登錄)一個程序時,他就是個依據,判斷你是否已經授權該軟件;cookie就是寫在客戶端的一個txt文件,里面包括你登錄信息之類的,這樣你下次在登錄某個網站,就會自動調用cookie自動登錄用戶名;session和cookie差不多,只是session是寫在服務器端的文件,也需要在客戶端寫入cookie文件,但是文件里是你的瀏覽器編號.Session的狀態是存儲在服務器端,客戶端只有session id;而Token的狀態是存儲在客戶端。

文章使用到的源碼

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

推薦閱讀更多精彩內容