Session 和 Cookie 的概念
網站通過 Session 和 Cookie 的機制記錄訪問者的一些基本信息,本小節依次講解 Cookie 和 Session 的概念,并講解了如何使用 Cookie 實現 Session。
1. 需求的提出
網站常常需要記錄訪問者的一些基本信息,例如:用戶是否登錄、用戶登錄名稱、密碼、用戶在 Web 站點購物的方式或用戶訪問該站點的次數。
舉個例子,用戶在沒有登陸 baidu 時,此時用戶的身份是游客,baidu 首頁的界面如下圖所示:
當用戶登陸 baidu 頁面后,此時用戶的身份是已登錄用戶,可以看到頁面的右上角顯示了用戶的名稱,如下圖所示:
可以看出,baidu 服務端能夠辨別用戶的身份,根據用戶是否登錄顯示不同的內容。如果用戶的身份是游客,則顯示文本登陸;如果用法的身份是已登錄用戶,則顯示用戶的名稱。
2. 使用 Cookie 辨別用戶身份
網站為了辨別用戶身份、進行會話跟蹤需要把一些數據 (例如:登錄狀態、用戶名稱) 儲存在用戶本地終端上,這些數據被稱為 Cookie。
以登錄 baidu 為例子,用戶在沒有登陸 baidu 時,訪問的網頁 URL 是 https://www.baidu.com;在登陸 baidu 后,訪問的網頁 URL 仍然是 https://www.baidu.com。訪問的頁面 URL 相同,但是這兩次訪問呈現的結果不相同,登陸前沒有顯示用戶名,登陸后顯示了用戶名。
服務端是通過 Cookie 的技術區分這兩次請求的,如下圖所示:
- 用戶登陸 baidu
- baidu 服務端會生成一個用戶 ID
- baidu 服務端將這個用戶 ID 發送給瀏覽器
- 瀏覽器收到這個用戶 ID 后,會將這個用戶 ID 保存在用戶本地終端
- 瀏覽器再次訪問 baidu 站點時,瀏覽器會將保存在本地的用戶 ID 發給 baidu 服務端
服務端收到瀏覽器發送的用戶 ID 后,就知道此次請求來自于一個已經登陸的用戶。在以上的交互過程中,保存在客戶端的用戶 ID 就被稱為 Cookie。
3. 發送 Cookie 的過程
3.1 在服務端發送 Cookie
通過設置 HTTP 的 Set-Cookie 消息頭,Web 服務器將 Cookie 發送給瀏覽器。Set-Cookie 消息的格式如下面所示,括號中的部分都是可選的:
Set-Cookie:value [ ;expires=date][ ;domain=domain][ ;path=path][ ;secure]
消息頭的第一部分,value 部分,通常是一個 name=value 格式的字符串。
服務端向客戶端發送的 HTTP 響應中設置 HTTP 的 Set-Cookie 消息頭,一個具體的例子如下:
Connection:keep-alive
Content-Type:text/plain
Date:Fri, 14 Jul 2017 10:49:23 GMT
Set-Cookie:user=ZhangSan
Transfer-Encoding:chunked
在這個例子中,服務端向客戶端發送的 HTTP 消息頭中,設置了 ‘Set-Cookie:user=ZhangSan’,客戶端瀏覽器將接受到字符串 ‘user=ZhangSan’ 作為 Cookie,下次訪問網站時,瀏覽器會將該 Cookie 發送給服務端。
3.2 在客戶端發送 Cookie
客戶端收到服務端的 Cookie 后,該 Cookie 會在接下來的每個請求中被發送至服務器。Cookie 的值被存儲在名為 Cookie 的 HTTP 消息頭中,并且只包含了 Cookie 的值,其它的選項全部被去除。
客戶端向服務端發送的 HTTP 請求中設置 Cookie 消息頭,一個具體的例子如下:
Connection:keep-alive
Cookie:user=ZhangSan
Host:localhost:8080
User-Agent:Mozilla/5.0 AppleWebKit/537.36 Chrome Safari
在這個例子中,客戶端向服務端發送的 HTTP 消息頭中,設置了 ‘Cookie:user=ZhangSan’,服務端接受到字符串 ‘user=ZhangSan’ 作為 Cookie,從而確認此次請求對應的用戶。
4. Session 簡介
Session 是在服務端保存的一個數據結構,用來存儲用戶的信息 (例如登錄狀態、用戶名稱),Session 數據可以保存在內存、文件或者數據庫中。Session 有一個唯一標識 SID (Session ID),對應一個用戶,在服務端使用 SID 可以查找到對應用戶的數據。
假設有 2 個用戶:用戶 A 和用戶 B;在服務端存在 2 個 Session,用于存儲用戶 A 和用戶 B 的數據,如下圖所示:
在服務端使用 SID 查找 Session 的過程如下:
- 每一個 Session 有一個唯一標識 SID,用戶 A 的 Sesion 的 SID 為 0,用戶 B 的 Sesion 的 SID 為 1;
- 用戶訪問網站時,會把自己的 SID 作為 Cookie 發送給服務端;
- 服務端則根據請求中的 SID 來尋找對應的 Session。
5. 使用 Cookie 實現 Session
通過一個具體的例子,解釋如何使用 Cookie 實現 Session。使用 Cookie 實現 Session 包含有兩個步驟:
1. 首次訪問,服務端發送 Set-Cookie 消息頭
首先,客戶端首次訪問網站時,服務端創建一個 Session 用于記錄用戶的信息,使用一個唯一的會話 ID 標識該 Session。
然后,服務端將會話 ID 通過 Set-Cookie 消息頭 (例如,Set-Cookie: sid=0) 發給客戶端,客戶端保存這個會話 ID。
在上圖中,存在兩個用戶:用戶 A 和用戶 B,服務端為它們分別創建一個 Session。每個 Session 擁有一個唯一的 SID,用戶 A 的 SID 等于 0,用戶 B 的 SID 等于 1。
2. 后續訪問,客戶端發送 Cookie 消息頭
客戶再次訪問服務端時,會將會話 ID 通過 Cookie 消息頭發給服務端,服務端根據請求中的 SID,尋找相應的 Session,該 Session 中存儲相應用的數據。最后,服務端將特定用戶的數據發給客戶端。
6. 小結
本小節講解了 Session 和 Cookie 的概念,使用思維導圖概括如下:
在下一個小節中,通過實例講解如何在 Flask 中使用 Cookie 和 Session。