在網站中,http請求是無狀態的。即服務器不知道用戶上一次做了什么,也就是說即使第一次和服務器連接后并且登錄成功后,第二次請求服務器依然不能知道當前請求是哪個用戶,之前做了什么操作。
典型的場景比如購物車,當你點擊下單按鈕時,由于HTTP協議無狀態,所以根本就不知道是哪個用戶操作,也不知道購物車里面都有哪些商品
所以當服務端需要記錄用戶的狀態時,就要用某種機制來進行識別和記錄,這也就是cookie和session
區別是,session多是存儲在服務器中,cookie多是存儲在客戶端中
## session
### session詳解
session代表服務器與瀏覽器的一次會話過程,這個過程可以是連續的,也可以時斷時續的。
session 是一個思路、一個概念、一個服務器存儲授權信息的解決方案,不同的服務器,不同的框架,不同的語言等都有不同的實現。
session是服務器生成的,有一個唯一標識。在服務端保存Session的方法很多,內存、數據庫、文件等等。集群的時候也要考慮session的轉移,在大型的網站,一般會有專門的session服務器集群,用來保存用戶會話,這個時候 session 信息都是放在內存的,使用一些緩存服務比如memcached之類的來放session。
### session工作原理
#### 1. 創建session
當用戶訪問到一個服務器,如果服務器啟用session,服務器就要為該用戶創建一個SESSION,在創建這個SESSION的時候,服務器首先檢查這個用戶發來的請求里是否包含了一個SESSION ID,如果包含了一個SESSION ID則說明之前該用戶已經登陸過并且服務器已經為此用戶創建過SESSION,那服務器就按照這個SESSION ID把這個SESSION檢索出來使用(如果檢索不到,就有可能為他新創建一個),如果客戶端請求里不包含有SESSION ID,則為該客戶端創建一個SESSION并生成一個與此SESSION相關的SESSION ID。這個SESSION ID是唯一的、不重復的、不容易找到規律的字符串,這個SESSION ID將被在本次響應中返回到客戶端保存,而保存這個SESSION ID的正是COOKIE,這樣在交互過程中瀏覽器可以自動的按照規則把這個標識發送給服務器。
#### 2. 使用session
SESSION ID 保存在cookie中,所以當瀏覽器再次訪問該網站時,會在請求頭中攜帶cookie訪問,服務器接收到cookie并解析出SESSION ID,并根據SESSION ID 找到相對應的SESSION
但是在瀏覽器選項中可以將cookie禁止,那么會不會出現把客戶端的cookie禁止,然后SESSION ID 無法再用的情況呢?
SESSION ID 仍然有其他機制在cookie被禁止時傳回服務器
經常被使用的一種技術是 **URL重寫**, 就是把Session id直接附加在URL路徑的后面作為URL路徑的附加信息,表現形式為:
http://…./xxx;jSession=ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764;
另一種是作為查詢字符串附加在URL后面,表現形式為:
http://…../xxx?jSession=ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764
還有一種就是表單隱藏字段,服務器會自動修改表單,添加一個隱藏字段,以便在表單提交時能夠把Session id傳遞回服務器
### session的優缺點
## cookie
### cookie詳解
Cookie(復數形態:Cookies),是指某些網站為了辨別用戶身份、進行session跟蹤而儲存在用戶本地終端上的數據(通常經過加密)。
cookie 存儲的數據量有限,不同的瀏覽器有不同的存儲大小,但一般不超過4KB。因此使用 cookie 只能存儲一些小量的數據。
cookie是有時間限制的,根據生命期不同分成兩種:會話cookie和持久cookie;
如果不設置過期時間,則表示這個cookie生命周期為從創建到瀏覽器關閉止,只要關閉瀏覽器窗口,cookie就消失了。這種生命期為瀏覽會話期的cookie被稱為會話cookie。會話cookie一般不保存在硬盤上而是保存在內存里。
如果設置了過期時間(MaxAge),瀏覽器就會把cookie保存到硬盤上,關閉后再次打開瀏覽器,這些cookie依然有效直到超過設定的過期時間。存儲在硬盤上的cookie可以在同一個瀏覽器的不同進程間共享,比如兩個IE窗口。而對于保存在內存的cookie,不同的瀏覽器有不同的處理方式。
### cookie工作原理
#### 1. 創建cookie
當用戶第一次瀏覽某個使用Cookie的網站時,該網站的服務器就進行如下工作:
1. 為該用戶生成一個唯一的識別碼(Cookie id),創建一個Cookie對象;
2. 默認情況下它是一個會話級別的cookie,存儲在瀏覽器的內存中,用戶退出瀏覽器之后被刪除。如果服務器希望瀏覽器將該Cookie存儲在磁盤上,則需要設置最大時效(maxAge),并給出一個以秒為單位的時間(將最大時效設為0則是命令瀏覽器刪除該Cookie)
3. 將Cookie放入到HTTP響應報頭,將Cookie插入到一個 Set-Cookie HTTP請求報頭中
4. 發送該HTTP響應報文
#### 2. 設置存儲cookie
瀏覽器收到該響應報文之后,根據報文頭里的Set-Cookied特殊的指示,生成相應的Cookie,保存在客戶端。該Cookie里面記錄著用戶當前的信息
#### 3. 發送cookie
當用戶再次訪問該網站時,瀏覽器首先檢查所有存儲的cookies,如果存在該網站的cookie,則把該cookie附在請求資源的HTTP請求頭上發送給服務器
#### 4. 讀取cookie
服務器接收到用戶的HTTP請求報文之后,從報文頭獲取到該用戶的Cookie,從里面找到所需要的東西。
### cookie的優缺點
## cookie和session的使用
web 開發發展至今, cookie 和 session 的使用已經出現了一些非常成熟的方案。在如今的市場或者企業里,一般有兩種存儲方式:
- 存儲在服務端:
通過 cookie 存儲一個 sessionid ,然后具體的數據則是保存在 session 中。如果用戶已經登錄,則服務器會在 cookie 中保存一個 sessionid ,下次再次請求的時候,會把該 sessionid 攜帶上來,服務器根據 sessionid 在 session 庫中獲取用戶的 session 數據。就能知道該用戶到底是誰,以及之前保存的一些狀態信息。這種專業術語叫做 server sidesession 。 Django 把 session 信息默認存儲到數據庫中,當然也可以存儲到其他地方,比如緩存中,文件系統中等。存儲在服務器的數據會更加的安全,不容易被竊取。但存儲在服務器也有一定的弊端,就是會占用服務器的資源,但現在服務器已經發展至今,處理一些 session 信息還是綽綽有余的。
- 將 session 數據加密,然后存儲在 cookie 中。
這種專業術語叫做 client side session 。 flask 框架默認采用的就是這種方式,但是也可以替換成其他形式。