Token是什麼?和session、cookie相比,使用場景有什麼區別?

95後程序猿小A


session和cookie

在講Token之前,先簡單說說什麼是session和cookie。

  • 首先要知道HTTP請求是無狀態的,也就是不知道這一次的請求和上一次請求是否有關係,比如我們登錄一個系統的時候,驗證用戶名密碼之後,打開系統各個頁面的時候就不需要再進行登錄操作了,直到我們主動退出登錄或超時退出登錄;這裡為了避免訪問每個都登錄一下,就要用到session、cookie。

  • cookie是在客戶端(瀏覽器)保存用戶信息的一種機制;而且每種瀏覽器存儲大小會有一些差異,一般不超過4KB;

  • session是在服務端保存,可以用於記錄客戶狀態,比如我們經常會用session保存客戶的基本信息、權限信息等;用戶第一次登錄之後,服務器就會創建一個session,瀏覽器再次訪問時,只需要從該session中查找該客戶的信息就可以了。

Token

但是這裡會有個問題,服務器要保存所有用戶的session信息,開銷會很大,如果在分佈式的架構下,就需要考慮session共享的問題,需要做額外的設計和開發,例如把session中的信息保存到Redis中進行共享;所以因為這個原因,有人考慮這些信息是否可以讓客戶端保存,可以保存到任何地方,並且保證其安全性,於是就有了Token。

Token是服務端生成的一串字符串,可以看做客戶端進行請求的一個令牌。

  • 當客戶端第一次訪問服務端,服務端會根據傳過來的唯一標識userId,運用一些加密算法,生成一個Token,客戶端下次請求時,只需要帶上Token,服務器收到請求後,會驗證這個Token。

  • 有些公司會建設統一登錄系統(單點登錄),客戶端先去這個系統獲取Token,驗證通過再拿著這些Token去訪問其他系統;API Gateway也可以提供類似的功能,我們公司就是這樣,客戶端接入的時候,先向網關獲取Token,驗證通過了才能訪問被授權的接口,並且一段時間後要重新或者Token。

基於Token的認證流程

整體的流程是這樣的:

  1. 客戶端使用用戶名、密碼做身份驗證;

  2. 服務端收到請求後進行身份驗證;(也可能是統一登錄平臺、網關)

  3. 驗證成功後,服務端會簽發一個Token返回給客戶端;

  4. 客戶端收到Token以後可以把它存儲起來(可以放在);每次向服務端發送請求的時候,都要帶著Token;

  5. Token會有過期時間,過期後需要重新進行驗證;

  6. 服務端收到請求,會驗證客戶端請求裡面的Token,驗證成功,才會響應客戶端的請求;


總結

  • cookie:保存在瀏覽器種,有大小限制,有狀態;

  • session:保存在服務器中,服務器有資源開銷,分佈式、跨系統不好實現;

  • Token:客戶端可以將Token保存到任何地方,無限制,無狀態,利於分佈式部署。

希望我的回答,能夠幫助到你!我將持續分享Java開發、架構設計、程序員職業發展等方面的見解,希望能得到你的關注。


會點代碼的大叔


這個問題,網上有很多的答案,相信都看過了,估計也沒有看明白。所以我就不去網上覆制了,用自己的話,儘量說通俗,說重點。

cookie和session實際上是同一套認證流程,相輔相成。session保存在服務器,cookie保存在客戶端。最常見的做法就是客戶端的cookie僅僅保存一個sessionID,這個sessionID是一個毫無規則的隨機數,由服務器在客戶端登錄通過後隨機生產的。往後,客戶端每次訪問該網站都要帶上這個由sessionID組成的cookie。服務器收到請求,首先拿到客戶端的sessionID,然後從服務器內存中查詢它所代表的客戶端(用戶名,用戶組,有哪些權限等)。

與token相比,這裡的重點是,服務器必須保存sessionID以及該ID所代表的客戶端信息。這些內容可以保存在內存,也可以保存到數據庫(通常是內存數據庫)。

而token則可以服務器完全不用保存任何登錄信息。

token的流程是這樣的。客戶端登錄通過後,服務器生成一堆客戶端身份信息,包括用戶名、用戶組、有那些權限、過期時間等等。另外再對這些信息進行簽名。之後把身份信息和簽名作為一個整體傳給客戶端。這個整體就叫做token。之後,客戶端負責保存該token,而服務器不再保存。客戶端每次訪問該網站都要帶上這個token。服務器收到請求後,把它分割成身份信息和簽名,然後驗證簽名,若驗證成功,就直接使用身份信息(用戶名、用戶組、有哪些權限等等)。

可以看出,相對於cookie/session機制,token機制中,服務器根本不需要保存用戶的身份信息(用戶名、用戶組、權限等等)。這樣就減輕了服務器的負擔。

我們舉個例來說,假如目前有一千萬個用戶登錄了,在訪問不同的網頁。如果用cookie/session,則服務器內存(或內存數據庫)中要同時記錄1千萬個用戶的信息。每次客戶端訪問一個頁面,服務器都要從內存中查詢出他的登錄信息。而如果用token,則服務器內存中不記錄用戶登錄信息。它只需要在收到請求後,直接使用客戶端發過來的登錄身份信息。

可以這麼說,cookie/session是服務器說客戶端是誰,客戶端才是誰。而token是客戶端說我(客戶端)是誰,我就是誰。當然了,token是有簽名機制的。要是客戶端偽造身份,簽名通不過。這個簽名算法很簡單,就是將客戶端的身份信息加上一個只有服務器知道的鹽值(不能洩露),然後進行md5散列算法(這裡只是簡化,方便理解,實際細節要稍複雜一些)。

cookie/session在單服務器,單域名時比較簡單,否則的話,就要考慮如何將客戶端的session保存或同步到多個服務器。還要考慮一旦宕機,內存中的這些信息是否會丟失。token因為服務器不保存用戶身份,就不存在這個問題。這是token的優點。

token因為服務器不保存用戶身份信息,一切都依賴當初那個簽名。所以存在被盜用的風險。也就是說一旦盜用,服務器可能毫無辦法,因為它只認簽名算法。而session機制,服務器看誰不爽,可以隨時把他踢出(從內存中刪掉)。正是因為如此,token高度依賴過期時間。過期時間不能太長。過期短,可以減少被盜用的風險。

除了上面所說的,我個人認為,如果開發的系統足夠小,傾向於使用cookie/session。如果系統同時登錄用戶多,集群服務器多,有單點登錄需求,則傾向於使用token。


犍為真人


Token顧名思義就是令牌、憑證、鑰匙。只有這把鑰匙,你才能打開門。token一般都是服務端生成,比如一個web系統,用戶登錄的時候,服務端校驗用戶名密碼通過以後,會生成一個token,同時會生成refreshToken和一個過期時間。然後將refreshToken和token返回給客戶端。客戶端會將token保存下來。後續所有的請求都會攜帶這個token。服務端會判斷當前token是否存在已經是否過期。如果token不存在或者過期就會拒絕本次請求。如果token過期怎麼辦,就用refreshToken刷新時間。當然這裡可能還有別的方案。比如只生成token,每次請求的時候都刷新過期時間。如果長時間沒有刷新過期時間,那token就會過期。


session就是回話,這是服務端的一種操作。當你第一次訪問一個web網站的時候,服務端會生成一個session,並有一個sessionid和他對應。這個session是存儲到內存中的,你可以向這個session中寫入信息,比如當前登錄用戶的信息。sessionid會被返回到客戶端,客戶端一般採用cookie來保存。當然這個cookie不用人為寫入。用tomcat容器來舉個例子。當後端調用HttpServletRequest對象的getSession的方法的時候,tomcat內部會生成一個jsessonid(tomcat sessionid的叫法)。這個jsessonid會隨本次請求返回給客戶端。響應頭信息

HTTP/1.1 200 OK
Set-Cookie: JSESSIONID=xxxxxxxxxxxxxxxxxxx

這個jessionid就會寫到cookie中。之後jessionid就會通過cookie傳遞到服務端。

這裡我們就會很清楚了,session的數據是存儲到內存中。那問題就來了,如果我們的服務是分佈式部署,有多臺機器的話,可能我們第一次登陸的時候,我們把用戶的信息存儲到了session,但是後面的請求到了B機器上,那B機器是獲取不到用戶的session的。另外就是session存儲在內存中,那服務器重啟,session就丟失了,這就是他的弊端。現在有一些技術,例如session共享、iphash、session持久等也可以解決上述問題。


cookie是瀏覽器的一種策略。上述講到了sessionid就是存儲在cookie中的。我們知道http協議是無狀態的,cookie就是用來解決這個問題的。cookie中可以用來保存服務端返回的一些用戶信息的,例如前文提到的token、sessionid。每一次的請求,都會攜帶這些cookie。服務端從請求頭中取到cookie中的信息,就可以識別本次請求的來源,這樣,http是不是就變成有狀態的了。
這裡說幾點cookie注意事項。

cookie是瀏覽器的一種策略。上述講到了sessionid就是存儲在cookie中的。我們知道http協議是無狀態的,cookie就是用來解決這個問題的。cookie中可以用來保存服務端返回的一些用戶信息的,例如前文提到的token、sessionid。每一次的請求,都會攜帶這些cookie。服務端從請求頭中取到cookie中的信息,就可以識別本次請求的來源,這樣,http是不是就變成有狀態的了。

這裡說幾點cookie注意事項。

1、cookie存放在客戶端,所以是不安全的。人為可以清除

2、cookie有過期時間設定。如果不設置過期時間,說明這個cookie就是當前瀏覽器的會話時間,瀏覽器關了,cookie 就存在了。如果有過期時間,cookie就會存儲到硬盤上,瀏覽器關閉不影響cookie。下次打開瀏覽器,cookie還存在

3、cookie有大小的限制,4KB。


阿邁達聊技術


在Web開發領域,相信大家對於Cookie和Session都很熟悉,Cookie和Session都是會話保持技術的解決方案。隨著技術的發展,Token機制出現在我們面前,不過很多開發者對於Token和Cookie、Session的區別及使用場景分辨不清。

Cookie和Session的用途

要知道我們訪問網站都是通過HTTP協議或HTTPS協議來完成的,HTTP協議它本身是無狀態的協議(即:服務器無法分辨哪些請求是來源於同個客戶)。而業務層面會涉及到客戶端與服務器端的交互(同網站下多個頁面間能共享數據),此時服務器端必須要保持會話狀態,這樣才能進行用戶身份的鑑別。

由於HTTP無狀態的特性,如果要實話客戶端和服務器端的會話保持,那就需要其它機制來實現,於是Cookie和Session應運而生。

通常情況下,Session和Cookie是搭配在一起使用的。

Token是什麼

上面說到的Session和Cookie機制來保持會話,會存在一個問題:客戶端瀏覽器只要保存自己的SessionID即可,而服務器卻要保存所有用戶的Session信息,這對於服務器來說開銷較大,而且不利用服務器的擴展(比如服務器集群時,Session如何同步存儲就是個問題)!

於是有人思考,如果把Session信息讓客戶端來保管而且無法偽造不就可以解決這個問題了?進而有了Token機制。

Token俗稱為“令牌”,它的構成是:

  • uid:用戶唯一身份標識

  • timestamp:當前時間戳

  • sign:簽名字符串,防止第三方偽造數據;簽名密鑰是存儲在服務器端的,其它人無法知道

  • 其它附加參數。

Token機制下的認證流程

Token機制其實和Cookie機制極其相似,主要有以下流程:

1、用戶登錄進行身份認證,認證成功後服務器端生成Token返回給客戶端;

2、客戶端接收到Token後保存在客戶端(可保存在Cookie、LocalStorage、SessionStorage中);

3、客戶端再次請求服務器端時,將Token作為請求頭放入Headers中;

4、服務器端接收請求頭中的Token,將用戶參數按照既定規則再進行一次簽名,兩次簽名若一致則認為成功,反之數據存在篡改請求失敗。


(生成簽名示例圖)

(驗證簽名示例圖)

Token與Cookie+Session的區別

Cookie其實也充當的是令牌作用,但它是“有狀態”的;而Token令牌是無狀態的,更利於分佈式部署。


以上就是我的觀點,對於這個問題大家是怎麼看待的呢?歡迎在下方評論區交流 ~ 我是科技領域創作者,十年互聯網從業經驗,歡迎關注我瞭解更多科技知識!


網絡圈


Token, 令牌,代表執行某些操作的權利的對象。

token主要用於鑑權使用,主要有以下幾類:

  • 訪問令牌(Access token)表示訪問控制操作主體的系統對象
  • 邀請碼,在邀請系統中使用
  • Token, Petri 網(Petri net)理論中的Token
  • 密保令牌(Security token),或者硬件令牌,例如U盾,或者叫做認證令牌或者加密令牌,一種計算機身份校驗的物理設備
  • 會話令牌(Session token),交互會話中唯一身份標識符
  • 令牌化技術 (Tokenization), 取代敏感信息條目的處理過程

cookie主要是網站用於在瀏覽器臨時存放的數據,包括瀏覽器緩存數據以及服務器設定的一些數據,主要存放在瀏覽器端。


session主要用於保存會話數據,一般存儲在服務器端,同時每一條session對用一個sessionID,sessionID是存放在瀏覽器的cookie中。


傳統上的會話登陸和鑑權主要用session加cookie實現,隨著分佈式系統的快速演進,尤其是微服務的應用,token+cookie的授權訪問機制得到親睞,通常在用戶登錄後,服務器生成訪問令牌(Access token),瀏覽器存儲cookie中,在每次請求資源時都會在請求頭中帶上token,用於服務器授權訪問使用。


分享到:


相關文章: