網站首頁 編程語言 正文
前言
今天就來理一理session、cookie、token這三者之間的關系!
1.為什么會有它們?
我們都知道 HTTP 協議是無狀態的,所謂的無狀態就是客戶端每次想要與服務端通信,都必須重新與服務端鏈接,意味著請求一次客戶端和服務端就連接一次,下一次請求與上一次請求是沒有關系的。
這種無狀態的方式就會存在一個問題:如何判斷兩次請求的是同一個人?就好比用戶在頁面 A 發起請求獲取個人信息,然后在另一個頁面同樣發起請求獲取個人信息,我們如何確定這倆個請求是同一個人發的呢?
為了解決這種問題,我們就迫切需要一種方式知道發起請求的客戶端是誰?此時,cookie、token、session 就出現了,它們就可以解決客戶端標識的問題,在擴大一點就是解決權限問題。
它們就好比讓每個客戶端或者說登錄用戶有了自己的身份證,我們可以通過這個身份證確定發請求的是誰!
2.什么是 cookie?
cookie 是保存在客戶端或者說瀏覽器中的一小塊數據,大小限制大致在 4KB 左右,在以前很多開發人員通常用 cookie 來存儲各種數據,后來隨著更多瀏覽器存儲方案的出現,cookie 存儲數據這種方式逐漸被取代,主要原因有如下:
- cookie 有存儲大小限制,4KB 左右。
- 瀏覽器每次請求會攜帶 cookie 在請求頭中。
- 字符編碼為 Unicode,不支持直接存儲中文。
- 數據可以被輕易查看。
cookie 主要有以下屬性:
屬性名稱 | 屬性含義 |
---|---|
name | cookie 的名稱 |
value | cookie 的值 |
comment | cookie 的描述信息 |
domain | 可以訪問該 cookie 的域名 |
expires | cookie 的過期時間,具體某一時間 |
maxAge | cookie 的過期時間,比如多少秒后 cookie 過期。 |
path | cookie 的使用路徑, |
secure | cookie 是否使用安全協議傳輸,比如 SSL 等 |
version | cookie 使用的版本號 |
isHttpOnly | 指定該 Cookie 無法通過 JavaScript 腳本拿到,比如 Document.cookie 屬性、XMLHttpRequest 對象和 Request API 都拿不到該屬性。這樣就防止了該 Cookie 被腳本讀到,只有瀏覽器發出 HTTP 請求時,才會帶上該 Cookie。 |
我們介紹了 cookie,那么我們是如何通過 cookie 來實現用戶確定或者權限的確定呢?
我們就以一個普通網站的用戶登錄操作以及后續操作為例,主要過程可以簡單用下圖表示:
從上圖中可以看到使用 cookie 進行用戶確認流程是比較簡單的,大致分為以下幾步:
- 客戶端發送請求到服務端(比如登錄請求)。
- 服務端收到請求后生成一個 session 會話。
- 服務端響應客戶端,并在響應頭中設置 Set-Cookie。Set-Cookie 里面包含了 sessionId,它的格式如下:Set-Cookie: value[; expires=date][; domain=domain][; path=path][; secure]。其中 sessionId 就是用來標識客戶端的,類似于去飯店里面,服務員給你一個號牌,后續上菜通過這個號牌來判斷上菜到哪里。
- 客戶端收到該請求后,如果服務器給了 Set-Cookie,那么下次瀏覽器就會在請求頭中自動攜帶 cookie。
- 客戶端發送其它請求,自動攜帶了 cookie,cookie 中攜帶有用戶信息等。
- 服務端接收到請求,驗證 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 認證流程:
- 客戶端發起登錄請求,比如用戶輸入用戶名和密碼后登錄。
- 服務端校驗用戶名和密碼后,將用戶 id 和一些其它信息進行加密,生成 token。
- 服務端將 token 響應給客戶端。
- 客戶端收到響應后將 token 存儲下來。
- 下一次發送請求后需要將 token 攜帶上,比如放在請求頭中或者其它地方。
- 服務端 token 后校驗,校驗通過則正常返回數據。
用圖表示大致如下:
總結
雖然前面解釋 cookie、session、token 用了不少口舌,但是歸根結底啊,它們的目的都是一樣的:鑒權和認證。
鑒權認證方式 | 特點 | 優點 | 缺點 |
---|---|---|---|
cookie | 1.存儲在客戶端。2.請求自動攜帶 cookie。3.存儲大小 4KB。 | 1.兼容性好,因為是比較老的技術。2.很容易實現,因為 cookie 會自動攜帶和存儲。 | 1.需要單獨解決跨域攜帶問題,比如多臺服務器如何共享 cookie。2.會遭受 CSRF 攻擊。3.存儲在客戶端,不夠安全。 |
session | 1.存儲在服務端。2.存儲大小無限制。 | 1.查詢速度快,因為是個會話,相當于是在內存中操作。2.結合 cookie 后很容易實現鑒權。3.安全,因為存儲在服務端。 | 1.耗費服務器資源,因為每個客戶端都會創建 session。2.占據存儲空間,session 相當于存儲了一個完整的用戶信息。 |
token | 1.體積很小。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默認機制下是不適合分布式部署的。
原文鏈接:https://blog.csdn.net/m0_65489440/article/details/125676761
- 上一篇:沒有了
- 下一篇:沒有了
相關推薦
- 2022-05-21 Kubernetes特別屬性的標簽Label的強大作用_服務器其它
- 2022-09-06 關于react+antd樣式不生效問題的解決方式_React
- 2022-08-15 SpringMVC異常處理流程總結
- 2022-06-14 golang連接redis庫及基本操作示例過程_Golang
- 2022-06-01 Python實現訪問者模式詳情_python
- 2021-12-29 Android中String與int相互轉換_Android
- 2022-12-28 Python中的Decorator裝飾器的使用示例_python
- 2022-07-27 python語法學習之super(),繼承與派生_python
- 欄目分類
-
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支