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