重要聲明:本文章僅僅代表了作者個人對此觀點的理解和表述。讀者請查閱時持自己的意見進行討論。
廢話不多說,直接上正文。 本文更新不及時,請到原文地址查看:【web】Session是什麼又和cookie有啥關係。
一、Session
無論你是Java作爲後臺,PHP作爲後臺,.Net 作爲後臺你都可以發現有一個方法可以獲取Session
這玩意兒。這或許就是你接觸Session
開始的地方。由於筆者本人對於Java更爲熟悉,因此將在java基礎上進行講解,實際上原理都是一樣的,不必擔心存在隔閡。
1、Session是什麼
Session
是存在於服務器端的。 你千萬不要想着Session
在瀏覽器裏,它在服務器端也是你能夠在後端的程序裏通過代碼獲取Session
最好的證據。細心的你肯定發現了,前端js代碼里根本就不會有獲取Session
相關的方法。
Session
就是一個鍵值對容器。 是的,它沒有你想象中的那麼複雜,它就是讓你從裏面獲取數據,或則你放數據在裏面的一個容器。而這個容器只不過維護着自己獨有的存活期。而通常情況下你不必關係這件事情。除非你有自己的功能實現需求在這一塊上面。
2、Sesison幹嘛的
你一定有過這樣的經歷,你打開某寶網站想要購物了,提示你登錄,然後你就登錄了。沒過一會兒,你又不想買了,把瀏覽器也給關閉了。但是又過了一會兒,你再次打開某寶網站,你發現你上次登錄的狀態還在,並沒有要你再一次進行登錄。
這就是因爲你訪問某寶時,某寶從Session
裏獲取到了你之前的登錄信息(之前登錄時會將信息保存在session),所以這次你就不必再進行登錄了。這無疑給用戶帶來了更好的體驗感受。所以,Session
既然是一個鍵值對容器,它就是拿來存一些數據的,通過這些緩存的數據,實現爲用戶帶來更方便操作感受。
3、Session怎麼產生的
Session
的產生不是單獨的,它必須和Cookie
協同工作,爲了更好的理解,這部分內容將在介紹完了Cookie
後進行一同講解。
二、Cookie
說得籠統點,Cookie
就是一個HTTP請求裏的Header裏面的一個鍵值。在發起HTTP請求時,在Header裏面添加一個名爲 cookie
的鍵,裏面的值就是會上傳給服務端的cookie值。你既可以在客戶端指定請求時要帶上什麼樣的Cookie
內容,也可以在響應時告訴客戶端有哪些cookie
會下發。你還需要注意,對於瀏覽器,瀏覽器總是會自動處理cookie,瀏覽器總是會自動將上次響應的cookie自動帶入到下次請求中(僅僅會把同域的cookie帶上,例如:aa.com下發的cookie,瀏覽器在下次訪問aa.com時會帶上這次下發的cookie。而不會把aa.com的cookie帶到bb.com上去)。
Cookie
的卻是上述所說的。但顯然不能只瞭解這點內容,爲了讓web服務更好的工作,它還有一定的規則定義在裏面。
1、Cookie的格式
不得不說Cookie
的格式是一種很奇葩的存在(不含貶義)。這裏我特指的是在傳輸過程中的表現格式,而不是cookie本身的定義格式。那麼下面我們慢慢道來:
2、響應Cookie的數據格式
幾乎大多數的請求響應裏都會包含Cookie
值,不過需要你注意的是,響應裏的cookie值,它的鍵
不是cookie
,而是set-cookie
,而且,特麼的如果有多個cookie在響應裏面,不是在同一個set-cookie
鍵裏面通過某特定字符分開,而是在響應頭裏面會有多個set-header
鍵,每個後面跟着一個不同的cookie
內容。下面是一份請求響應示列:
這是一份使用<postman>工具進行請求百度從而獲取到的請求和響應日誌。可以看到,紅色線框區域內,百度服務端給我們響應了4個cookie
。這樣看來,對cookie響應的格式就非常清晰了。下面介紹一下Cookie
本身的定義格式含義:
3、Cookie的格式
Cookie
有幾個固有字段的定義,它們分別如下:
字段 | 含義 |
---|---|
expires | 表示此cookie的過期時間,這是一個時間值,過了這個時間,就不應該再把此cookie提交到服務端了。 |
max-age | 表示此cookie的過期時間,這是一個時間段值,請求時間+maxAge = 實際過期的時間。 |
path | 表示此cookie能在哪些路徑下提交到服務端 |
domain | 表示此cookie能提交給哪些域或子域名下 |
version | 表示版本號 |
comment | 描述,相當於一個對cookie的註釋 |
secure | 表示此cookie只能在https的請求中被提交 |
httponly | 表示此cookie只能在響應和請求中傳遞,不能將此cookie暴露給開發者操作。也就說明了不能在JavaScript裏面獲取這樣的cookie。 |
samesite | 爲了防止 CSRF 攻擊和用戶追蹤,有關此項請點擊Cookie 的 SameSite 屬性查看詳情 |
在響應數據裏,這些字段都是通過;號
來間隔各個字段屬性。把這些字段去除,剩下的就是cookie
本身的鍵值內容了。
例如:上圖中的cookie本身鍵值內容則是:
BD_NOT_HTTPS=1
BIDUPSID=ED2D87A3418138376C6A292B1702A386
PSTM=1577674617
BAIDUID=ED2D87A341813837A5C1FDA5B3D5B76E:FG=1
4、請求Cookie的格式
通過上面的分析,我們拿到了實際上cookie要傳遞的鍵值對內容。那麼在下次請求時,就要帶上這些cookie,這是http協議規定如此的。不過具體請求時要傳遞哪些內容,又受到了Cookie
本身固有字段的各種值的限定。假設我們現在已經拿到了上述cookie,那麼在下次提交請求時,則需要將Cookie這樣提交:
上圖紅色線框中就是提交的cookie,可以看到它和響應時的cookie風格不太一樣,甚至大不一樣。不再是一個cookie一條數據,而是將所有的cookie值,根據cookie自身固定屬性判斷後,通過;號
分割各個cookie,然後拼接成一個整體,將這個整體以header中的cookie
這個鍵提交上去。
響應結果裏百度服務端又給我們響應了新的cookie內容,這時候就應該再次保存這些新的cookie,留給下次使用。
從這裏也可以看出,要從一個請求(request)裏獲取cookie,怎麼獲取?直接從header中取cookie
這個鍵,拿到的值就是客戶端提交上來的第一手cookie值。
三、Session與Cookie的不謀而合
我們知道Cookie總是會被瀏覽器自動處理,下次自動提交。那麼,爲了更好的提供服務,如果後端能夠將某用戶的某次訪問數據緩存下來,那麼用戶下次訪問時這些緩存數據就必然會提供用戶更加個性化和遍歷的使用體驗。這時候問題就來了,服務端要緩存用戶的數據,首先服務端就要有一個東西來確定這部分緩存數據是對應這個用戶的,才能正確的實現這個功能。而什麼樣的一種解決方案可以實現呢,沒錯,Cookie
這玩意兒看起來很符合我們的需求。
當某個用戶初次訪問M網站
時,瀏覽器由於以前從來沒有訪問過,所以沒有任何cookie提交到M網站
。當網站服務端發現沒有Cookie,不得不新創建一個Session
緩存區域,創建完成後M網站
就會把用於確定這個Seesion
唯一性的Id值放在響應的cookie裏面,唉~~這不就會被瀏覽器自動保存了嘛,然後下次請求的時候,瀏覽器又總是自動將cookie提交的,自然而然的,就把服務端之前放在cookie裏的ID值又給傳到了服務端,當服務端發現cookie裏面有一個id,就會去嘗試獲取對應的Session
,這樣一來,你的Session
緩存區域不就又被獲取到了,還是上次那個,緩存數據獲取也變得輕鬆起來。
這樣的邏輯過程似乎非常棒,不過又不得不讓人產生疑問,難道這個Sesion就這樣一直可以保存着,用戶越來越多,被分配的Session不也就越來越多,哪有那麼多內存呢。所以Session是有過期時間的。
四、Session的過期
通常來說,Sesison
的過期時間是30分鐘,不過這是可以修改的。這個過期時間的計時方式不是從創建Sesison開始計時,而是從最後一次訪問這個Session
開始計時。當Session
過期了之後,服務端會自動又創建一個新的,然後將新的id放在cookie裏。
五、總結
經過了這麼多的解釋,現在把這整篇文章歸結爲兩個字,他就是:“會話”。這樣的描述非常符合Session的作用和意圖,它就像用戶打開了網站,被認爲開啓了和服務端的一次“會話”。
我講完了。