關於 Session 與 Cookie - < Session篇 > 紀錄
前陣子在幫忙開發公司的 Nodejs 專案,在處理上,發現自己對 Cookie 和 Session 的概念還沒有很清晰,所以研究了一下,在此紀錄,也順便分享出來。
雖然我的 Blog 應該是 SEO 差到爆的邊緣 Blog, 不過自己也滿喜歡紀錄的,就邊學邊整理下來,有緣人若看到此篇,歡迎與我討論,如果有錯煩請指教。
底下的紀錄也參考了諸多篇文章與大大的 Blog, 如有一些雷同的敘述,請見諒 🙏
要搞懂一個東西,就要不斷問 "為什麼" 和 "如何" 。
< 此次紀錄重點 >
雖然很多人在解釋 Session 時會與 Cookie 一起解釋,但此篇我想先盡量專注在 Session ,先不與 Cookie 混著談。
< 什麼是 Session 統整 >
各方解釋:
-
從字本身語義切入
- 具有狀態的一段時間
- 上下文
- 中文翻譯: "會話"
-
生活例子: 有始有終的一系列動作/消息
- ex: 打電話是從拿起電話撥號到掛斷電話,這中間的一系列過程稱之為一個 session
-
當 Session 與網路協議相關時:
- 有連接或保持狀態的意思
-
當 Session 在 Web 開發領域時有一些詮釋:
-
概念:
- 將 Client端 與 Server端之間交互的過程,抽象為"會話",進而衍生出 "會話的狀態"(偵測/觀測交互過程的狀態),也就是說這時的 Session 是一種概念
-
狀態管理的解決方案/機制/實現:
-
i. Client端 與 Server端之間保持狀態的 "解決方案(機制)",也就是說這時後,Session 指的是一種狀態管理的解決方式(機制)
-
ii. Session 是一種 Server端的機制,Server 使用一種類似於 Hash Table(雜湊表/散列表/哈希表) (也可能就是 Hash Table)的結構來保存訊息,在這 Session 指的也是一種狀態管理的解決方式(機制)
-
-
儲存結構:
- Client端 與 Server端之間保持狀態的 "解決方案(機制)的存儲結構",也就是說這時候,Session 指的是一種狀態管理的解決方式(機制)的 "儲存結構"
-
資料(狀態/資訊)本身:
- 因為 1. 的概念而衍伸出,在建立 2. 的狀態管理的解決機制後我們透過 3. 的儲存結構去把所要儲存的狀態儲存起來,這些狀態有時會看到有人寫直接就說是 Session Information(Session 資訊)。所以有時候人家說 Session 也有可能指的是 Session 資訊本身,
Session == Session 資訊 ?
所以我覺得概念還是要懂,比次溝通才會比較順,默契也比較好,因為技術名詞有時候就是有點曖昧,說到這自己的實力還是不行啊....加油!
- 因為 1. 的概念而衍伸出,在建立 2. 的狀態管理的解決機制後我們透過 3. 的儲存結構去把所要儲存的狀態儲存起來,這些狀態有時會看到有人寫直接就說是 Session Information(Session 資訊)。所以有時候人家說 Session 也有可能指的是 Session 資訊本身,
-
< 什麼是 Session 自我統整 >
所以會發現當我們單純說 Session 時,其實有太多定義模糊的空間。
自己統整後,
Session 的含義可以有以下數種:
1. 含義1:
在平常生活上單單就單字用法就是指具有狀態的一段時間、會議、開會、一次交流。 如果有在跳舞的人可能常聽到 Session 這個字眼,每當聽到這個詞時,可能會是指一次比賽的出場,一次活動,一個round, 一段時間內彼此的跳舞交流時間。
2. 含義2:
接下來開始試著慢慢引導到 Web 相關的含義。 Session 與網路協議相關時,有時是「連接」的意思: 舉例1. 比如當你要建立通信的渠道,像是打電話,你要確定對方接了電話通信才開始,這也是 Session 的含義之一。 舉例2. 一樣是建立通信的渠道, 像是寫信,你寫出去時不確定地址對不對,雖然收信人不一定能收到,但僅僅對於發信人來說,他也會認為這個 Session 已經開始了,這也是一種 Session 的表現。
3. 含義3:
Session 與網路協議相關時,另一個意思是「保持狀態」的意思: 這個保持狀態指的是,在連接之餘,連接的一方能夠把一系列相關的訊息(狀態/資訊)關聯起來,比如說常去吃的麵攤老闆娘她一眼就能記得上次你忘記帶錢說要這次來再付,也記得你最愛點的海鮮麵,直接就幫你做了,這類「保持狀態」的例子有「一個 TCP session」, 「一個 POP3 session」
4. 含義4:
Session 進到 Web App的領域時: Session 在現今 Web開發領域下,可以指 Client 端與 Server 端之間交互的過程,有時會把這個過程統整成「會話」這個詞,此時的 Session 是一種整體的概念。
5. 含義5:
當我們知道 Session 可以指有始有終的一系列動作(狀態/消息)時,ex: 像是打電話從撥號到掛斷的一系列過程。 所以有時看到「在一個 Browser 的會話期間..」是指從瀏覽器視窗打開到關閉的這個期間就叫做一個 Session。
6. 含義6:
有時看到「 Client 的一次會話期間..」可以指同個目的的一系列動作,像是從登錄到選購商品到結帳登出,這樣的一個過程可以稱作一個 Session, 同時也可被稱為是在資料處理上的一次 transaction,所以在「 Client 的一次會話期間..」的解釋下,開發者在彼此溝通時要理解這個過程的頭跟尾到底彼此指的一不一樣。因為有時候可能 A 想的只是一次性的某個動作期間,但 B 所想的是好幾個動作合起來的期間。
7. 含義7:
所以當我們從含義4, 5, 6 解釋過來會發現,這個交互的過程其實也從一種概念演變成實際運行的機制,也就變成較偏向大家所認知的 Session 定義的其中一種,就是 Client端與 Server端之間保持狀態的「機制(解決方案)」。
8. 含義8:
那當有人問說你是「存在 Cookie 還是 Session時?」這句話在我以前剛學程式時,覺得問這樣的一個問題沒什麼,也挺專業的(太無知了..),但經過我的研讀和查閱,我認為事實是問問題還是必須問的精確一點比較好,此篇不討論 Cookie,Cookie 確實是一個儲存的空間,但存在 Session 就有點不太精確,硬要解釋,大部分都是解釋成實作 Session 這種機制的作法,把資料存在一些可以存資料的地方,像是記憶體(Memory)、快取(Cache)、Cookie、資料庫(Database),所以當這樣的一個問題出現時,無法去定義此時的 Session 是什麼,我們可以猜測的是也許此刻的 Session 指的是資料放的地方。或是另一個含義像是含義 9。
9. 含義9:
根據含義8,有時 Session 也會指實踐 Session 機制時,資料被儲存時本身的資料結構。
10. 含義10:
根據含義7, 8, 9,我們可以知道資料(狀態/資訊)本身,也有機會被稱為 Session,當我們說「拿 Session 資料」,雖然比較不會被認為 Session 本身就是資料,但還是要記得有這麼一個可能性。
11. 含義11:
不同的語言及框架在實踐 Session 概念時,也會有不同作法,此時的 Session 就會因此而有些各方實作及定義上的差異。
< 為什麼出現 Session >
各方解釋:
-
HTTP Stateless:以無狀態角度切入
- 由於 Http 為 Stateless protocol(無狀態協議),但在 Web 領域中,server 時常需要紀錄 User 的狀態,但 Http 是無狀態的,所以就需要某種機制來紀錄識別用戶的狀態,而 Session 就出場了。
-
我認為合理的簡單解釋:
- 解決無狀態,Session 出現幫忙
- 根據 RFC 2109 session 可以指一種交互狀態(關係),這裡面包括 Client 的 Request 和 Server 的 Response 之間的交互內容,最早會出現,裡面也提及是因為要建立 Stateful,裡面說道:
3. STATE AND SESSIONS
This document describes a way to create stateful sessions with HTTP
requests and responses. Currently, HTTP servers respond to each
client request without relating that request to previous or
subsequent requests; the technique allows clients and servers that
wish to exchange state information to place HTTP requests and
responses within a larger context, which we term a "session". This
context might be used to create, for example, a "shopping cart", in
which user selections can be aggregated before purchase, or a
magazine browsing system, in which a user's previous reading affects
which offerings are presented.
There are, of course, many different potential contexts and thus many
different potential types of session. The designers' paradigm for
sessions created by the exchange of cookies has these key attributes:
1. Each session has a beginning and an end.
2. Each session is relatively short-lived.
3. Either the user agent or the origin server may terminate a
session.
4. The session is implicit in the exchange of state information.
This document describes a way to create stateful sessions with HTTP requests and responses. Currently, HTTP servers respond to each client request without relating that request to previous or subsequent requests;
the technique allows clients and servers that wish to exchange state information to place HTTP requests and responses within a larger context, which we term a "session".
更詳細可以參考: Huli大大這篇
< Session 資訊 儲存位置 >
1. 記憶體
- 小應用在開發環境時,如果不需要共享狀態的情況下,存記憶體是個方便的方式,但除此之外也沒有什麼好處。
2. Cookie
- 把 Session 資訊存在 Cookie,也就是不是 Server 存狀態了,是 Client 存,所以每次 request 都會直接帶上 Session 資訊,所以不用擔心需要共享狀態的問題,安全性問題的話,按照一般做法一定會做處理(比如說 SignedCookie的作法)等等,真正比較大的問題是資料傳輸的量變大。
3. 快取 (ex: Redis)
- 這是大部份最常用的方式,特點快,也可以共享狀態,相比存在 Cookie ,當 Session 資訊量大的時候,可以節省網路的傳輸。
4. 資料庫
- 依需求使用,一般不常出現。
< 實踐 Session 概念(機制)的兩種方式 >
- Cookie-Based Session (也就是 Client Side Session)
- 使用 SessionID (也就是 Server Side Session )
-
- 所謂 Cookie-based session 指的是,今天要存的資料(狀態)都放在 cookie ,有可能是明文存,也有可能是處理過(編碼、加密)存,但基本上安全性問題,就算放基本上都會加密,缺點是:存太多東西在 Cookie ,會變得太笨重。
-
- SessionID 的使用方式是,把資料、狀態存在 Server,然後 Server 傳的 Set-cookie 是傳一個 SessionID,這個 SessionID 的做用就是當 Browser 傳過來 Server 時,Server 會去比對這個 SessionID 是不是跟當初一開始發給 Browser 時的紀錄是一樣的,相當於一個 Key,利用這個 SessionID 去換存在 Server 的資料、狀態,如此在 Server 和 Browser 就可以維持狀態紀錄,解決 HTTP Stateless
RFC 6265 提到關於 SessionID 的例子
< RFC 6265 >
Using the Set-Cookie header, a server can send the user agent a short string in an HTTP response that the user agent will return in future HTTP requests that are within the scope of the cookie. For example, the server can send the user agent a "session identifier" named SID with the value 31d4d96e407aad42. The user agent then returns the session identifier in subsequent requests.
< 實踐 Session 概念(機制)的其他種方式 >
- form 裡面放一個 hidden 的欄位
<form name="testform" action="/xxx">
<input type="hidden" name="jsessionid" value="ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764">
<input type="text">
</form>
- 網址列帶資訊(URL重寫)
http://...../xxx;jsessionid= ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764
http://...../xxx?jsessionid=ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764
< 實踐 Session 概念(機制)最常見做法 >
- Server 如果需要 session (概念or機制or結構)。看怎麼解釋,但通常大家在說的就是,存某些狀態在 Server。那最常見的就是,Server 它想初始化一個 session,於是它就回傳一個 Set-Cookie 的 Header 到 User Agent, 如果這時候 Browser 決定繼續這個 session 的話,可以回傳 Cookie 這個 Header。
這也是當初 RFC2109 rfc2109 (ietf.org)的片段所描述的,也是我們現在常常在做的事,利用 Cookie 去實現 session 這個功能。
< The End >
接下來再找時間寫 Cookie 及其他相關紀錄
Self Checklist:
- Explain what is
Session
. - Understand
Session
can means lots of things. - Know how to resolve problem with
Session
.
Reference:
- https://www.zhihu.com/question/19786827
- https://blog.techbridge.cc/2019/08/10/session-and-cookie-rfc/
- https://datatracker.ietf.org/doc/html/rfc2109
- https://fred-zone.blogspot.com/2014/01/web-session.html
- https://iter01.com/194145.html
- https://blog.hellojcc.tw/introduce-session-and-cookie/
- https://wiki.jikexueyuan.com/project/node-lessons/cookie-session.html
- https://juejin.cn/post/6844904073934667790
- https://yken919.pixnet.net/blog/post/45702341