首頁 > 軟體

一文徹底理清session、cookie、token的區別

2023-02-28 18:01:49

前言

今天就來理一理session、cookie、token這三者之間的關係!

1.為什麼會有它們?

我們都知道 HTTP 協定是無狀態的,所謂的無狀態就是使用者端每次想要與伺服器端通訊,都必須重新與伺服器端連結,意味著請求一次使用者端和伺服器端就連線一次,下一次請求與上一次請求是沒有關係的。

這種無狀態的方式就會存在一個問題:如何判斷兩次請求的是同一個人?就好比使用者在頁面 A 發起請求獲取個人資訊,然後在另一個頁面同樣發起請求獲取個人資訊,我們如何確定這倆個請求是同一個人發的呢?

為了解決這種問題,我們就迫切需要一種方式知道發起請求的使用者端是誰?此時,cookie、token、session 就出現了,它們就可以解決使用者端標識的問題,在擴大一點就是解決許可權問題。

它們就好比讓每個使用者端或者說登入使用者有了自己的身份證,我們可以通過這個身份證確定發請求的是誰!

2.什麼是 cookie?

cookie 是儲存在使用者端或者說瀏覽器中的一小塊資料,大小限制大致在 4KB 左右,在以前很多開發人員通常用 cookie 來儲存各種資料,後來隨著更多瀏覽器儲存方案的出現,cookie 儲存資料這種方式逐漸被取代,主要原因有如下:

  • cookie 有儲存大小限制,4KB 左右。
  • 瀏覽器每次請求會攜帶 cookie 在請求頭中。
  • 字元編碼為 Unicode,不支援直接儲存中文。
  • 資料可以被輕易檢視。

cookie 主要有以下屬性:

屬性名稱屬性含義
namecookie 的名稱
valuecookie 的值
commentcookie 的描述資訊
domain可以存取該 cookie 的域名
expirescookie 的過期時間,具體某一時間
maxAgecookie 的過期時間,比如多少秒後 cookie 過期。
pathcookie 的使用路徑,
securecookie 是否使用安全協定傳輸,比如 SSL 等
versioncookie 使用的版本號
isHttpOnly指定該 Cookie 無法通過 JavaScript 指令碼拿到,比如 Document.cookie 屬性、XMLHttpRequest 物件和 Request API 都拿不到該屬性。這樣就防止了該 Cookie 被指令碼讀到,只有瀏覽器發出 HTTP 請求時,才會帶上該 Cookie。

我們介紹了 cookie,那麼我們是如何通過 cookie 來實現使用者確定或者許可權的確定呢?

我們就以一個普通網站的使用者登入操作以及後續操作為例,主要過程可以簡單用下圖表示:

從上圖中可以看到使用 cookie 進行使用者確認流程是比較簡單的,大致分為以下幾步:

  1. 使用者端傳送請求到伺服器端(比如登入請求)。
  2. 伺服器端收到請求後生成一個 session 對談。
  3. 伺服器端響應使用者端,並在響應頭中設定 Set-Cookie。Set-Cookie 裡面包含了 sessionId,它的格式如下:Set-Cookie: value[; expires=date][; domain=domain][; path=path][; secure]。其中 sessionId 就是用來標識使用者端的,類似於去飯店裡面,服務員給你一個號牌,後續上菜通過這個號牌來判斷上菜到哪裡。
  4. 使用者端收到該請求後,如果伺服器給了 Set-Cookie,那麼下次瀏覽器就會在請求頭中自動攜帶 cookie。
  5. 使用者端傳送其它請求,自動攜帶了 cookie,cookie 中攜帶有使用者資訊等。
  6. 伺服器端接收到請求,驗證 cookie 資訊,比如通過 sessionId 來判斷是否存在對談,存在則正常響應。

cookie 主要有以下特點:

  • cookie 儲存在使用者端
  • cookie 不可跨域,但是在如果設定了 domain,那麼它們是可以在一級域名和二級域名之間共用的。

3.什麼是 session?

在上一節中,我們通過 Cookie 來實現了使用者許可權的確認,在其中我們提到了一個詞:session。顧名思義它就是對談的意思,session 主要由伺服器端建立,主要作用就是儲存 sessionId,使用者與伺服器端之間的許可權確認主要就是通過這個 sessionId。

簡單描述下 session:

session 由伺服器端建立,當一個請求傳送到伺服器端時,伺服器會檢索該請求裡面有沒有包含 sessionId 標識,如果包含了 sessionId,則代表伺服器端已經和使用者端建立過 session,然後就通過這個 sessionId 去查詢真正的 session,如果沒找到,則為使用者端建立一個新的 session,並生成一個新的 sessionId 與 session 對應,然後在響應的時候將 sessionId 給使用者端,通常是儲存在 cookie 中。如果在請求中找到了真正的 session,驗證通過,正常處理該請求。

總之每一個使用者端與伺服器端連線,伺服器端都會為該使用者端建立一個 session,並將 session 的唯一標識 sessionId 通過設定 Set-Cookie 頭的方式響應給使用者端,使用者端將 sessionId 存到 cookie 中。

通常情況下,我們 cookie 和 session 都是結合著來用,當然你也可以單獨只使用 cookie 或者單獨只使用 session,這裡我們就將 cookie 和 session 結合著來用。

我們可以在修改一下整個請求過程圖,如下所示:

4.cookie 和 session 的區別?

前面兩節我們介紹了 cookie 和 session,它們兩者之間主要是通過 sessionId 關聯起來的,所以我們總結出:sessionId 是 cookie 和 session 之間的橋樑。我們日常的系統中如果在鑑權方面如果使用的是 cookie 方式,那麼大部分的原理就和我們前面說的一樣。

或者我們可以換個說法,session 是基於 cookie 實現的,它們兩個主要有以下特點:

  • session 比 cookie 更加安全,因為它是存在伺服器端的,cookie 是存在使用者端的。
  • cookie 只支援儲存字串資料,session 可以儲存任意資料。
  • cookie 的有效期可以設定較長時間,session 有效期都比較短。
  • session 儲存空間很大,cookie 有限制。

系統想要實現鑑權,可以單獨使用 cookie,也可以單獨使用 session,但是建議結合兩者使用。

5.token 是什麼?

前面我們說的 sessionId 可以叫做令牌,令牌顧名思義就是確認身份的意思,伺服器端可以通過令牌來確認身份。

cookie+session 是實現認證的一種非常好的方式,但是凡事都有兩面性,它們實現的認證主要有以下缺點:

  • 增加請求體積,浪費效能,因為每次請求都會攜帶 cookie。
  • 增加伺服器端資源消耗,因為每個使用者端連線進來都需要生成 session,會佔用伺服器端資源的。
  • 容易遭受 CSRF 攻擊,即跨站域請求偽造。

那麼為了避免這些缺點,token 方式的鑑權出現了,它可以說是一個民間的認證方式,但是不得不說它帶來了非常多的好處。

token 的組成:

token 其實就是一串字串而已,只不過它是被加密後的字串,它通常使用 uid(使用者唯一標識)、時間戳、簽名以及一些其它引數加密而成。我們將 token 進行解密就可以拿到諸如 uid 這類的資訊,然後通過 uid 來進行接下來的鑑權操作。

token 是如何生成的:

前面我們說 cookie 是伺服器端設定了 set-cookie 響應頭之後,瀏覽器會自動儲存 cookie,然後下一次傳送請求的時候會自動把 cookie 攜帶上。但是我們說 cookie 算是一種民間的實現方式,所以說瀏覽器自然不會對它進行成麼處理。token 主要是由伺服器生成,然後返回給使用者端,使用者端手動把 token 存下來,比如利用 localstorage 或者直接存到 cookie 當中也行。

token 認證流程:

  1. 使用者端發起登入請求,比如使用者輸入使用者名稱和密碼後登入。
  2. 伺服器端校驗使用者名稱和密碼後,將使用者 id 和一些其它資訊進行加密,生成 token。
  3. 伺服器端將 token 響應給使用者端。
  4. 使用者端收到響應後將 token 儲存下來。
  5. 下一次傳送請求後需要將 token 攜帶上,比如放在請求頭中或者其它地方。
  6. 伺服器端 token 後校驗,校驗通過則正常返回資料。

用圖表示大致如下:

總結

雖然前面解釋 cookie、session、token 用了不少口舌,但是歸根結底啊,它們的目的都是一樣的:鑑權和認證。

鑑權認證方式特點優點缺點
cookie1.儲存在使用者端。2.請求自動攜帶 cookie。3.儲存大小 4KB。1.相容性好,因為是比較老的技術。2.很容易實現,因為 cookie 會自動攜帶和儲存。1.需要單獨解決跨域攜帶問題,比如多臺伺服器如何共用 cookie。2.會遭受 CSRF 攻擊。3.儲存在使用者端,不夠安全。
session1.儲存在伺服器端。2.儲存大小無限制。1.查詢速度快,因為是個對談,相當於是在記憶體中操作。2.結合 cookie 後很容易實現鑑權。3.安全,因為儲存在伺服器端。1.耗費伺服器資源,因為每個使用者端都會建立 session。2.佔據儲存空間,session 相當於儲存了一個完整的使用者資訊。
token1.體積很小。2.自由操作儲存在哪裡。1.安全,因為 token 一般只有使用者 id,就算被擷取了也沒什麼用。2.無需消耗伺服器記憶體資源,它相當於只存了使用者 id,session 相當於儲存了使用者的所有資訊。3.跨域處理較為方便,比如多臺伺服器之間可以共用一個 token。1.查詢速度慢,因為 token 只存了使用者 id,每次需要去查詢資料庫。

總結下來就是:session 是空間換時間,token 是時間換空間。

附:cookie/session的聯絡

session雖說存放在伺服器端,但是仔細看剛才的執行流程你會明白,session是依賴於cookie的,這一點也是本篇文章想要著重強調的

7.cookie/session使用注意事項

1.cookie大小有限制 4k

2.cookie不能跨瀏覽器

3.cookie不支援中文

4.如果是安全性較高的資料應存放在session中,因為cookie存放在使用者端總會輕易被不法分子獲取

5.如果是存取量特別大的網站,儘量不要在session中儲存使用者資料,因為每個使用者存一個session會給伺服器造成很大的壓力

但需要注意的是,若伺服器做了負載均衡,使用者的下一次請求可能會被定向到其它伺服器節點,若那臺節點上沒有使用者的Session資訊,就會導致對談驗證失敗。所以Session預設機制下是不適合分散式部署的。

到此這篇關於session、cookie、token區別的文章就介紹到這了,更多相關session、cookie、token區別內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com