---
# System prepended metadata

title: Cookie & Session - 筆記
tags: [authentication, HTTP, web security, cookie, session]

---

# Cookie & Session - 筆記

###### tags: `HTTP` `cookie` `session` `authentication` `web security`
:::warning
:bulb: 本站筆記已同步更新到我的[個人網站](https://simplydevs.netlify.app/)囉! 歡迎參觀與閱讀，體驗不同的視覺感受!
:::
[TOC]

## :memo: HTTP 的無狀態 (Stateless) 特性
HTTP通訊協定(HTTP Protocol)具無狀態(Stateless)的特性，這表示每個伺服器所接收的HTTP request是獨立的，並且與先前接收到的request不相關。伺服器不會保存client的狀態，因此伺服器給予的response是根據當下的狀態。

**無狀態協定具有特性如下:**
* 簡化了伺服器的設計
* 因為系統不需要追蹤多個連結通訊與session的細節，因此無狀態協定所需資源較少。
* 在無狀態協定中，各個封包(packet)各自運輸，與其他封包無涉
* 伺服器與客戶端之間的依賴程度低

因此，如果我們希望伺服器能認出 request 的狀態 (例如之前已經登入)，我們可以讓 request 本身攜帶充足的資訊，來幫助伺服器判斷這個 request 是否為會員系統裡的某位使用者，再進一步判斷這位使用者的狀態。而所謂「讓 request 本身攜帶充足的資訊」，類似會員卡的概念，我們會**讓 request 攜帶一串憑證，伺服器可以用這串憑證進一步查找資料庫裡的使用者資訊，cookie就是達成這種目的的一種憑證**。

## :memo: 憑證

### 用戶端如何保存憑證
保存憑證的方法有很多種，瀏覽器本身提供了 cookie 和 web storage 等機制，如果有特殊目的，也可以拉出去儲成獨立的外部檔案。
![](https://i.imgur.com/Md0uYhL.png)
<p style="text-align:center">兩種不同的web session管理機制</p>
<h6 style="text-align:center;">(Source: Alpha Camp material)</h6>

### 伺服器如何比對 request 攜帶的憑證？
真正的使用者資料存在資料庫裡，所以在應用程式伺服器上也需要建立一個儲存機制，才能把用戶端、應用程式伺服器、資料庫三個地方的資訊匹配起來。

在應用程式伺服器上，用來存放使用者狀態的機制，稱為 session。
### **Session** 

![](https://i.imgur.com/MpFovoF.png)

<p style="text-align:center">session與cookie儲存使用者資訊的方式</p>
<h6 style="text-align:center">(Source: Alpha Camp material)</h6>

Session 翻譯成「會話」，這是抽象的概念，代表 **「用戶端與伺服器之間一系列的交流」**，你可以把一個「登入-登出」的週期視為一次「會話」。
* 通常「伺服器的 session」和「用戶端的 cookie」是相對存在的解決方案。
* session 也是一個 key-value pair 的結構，可以先想像成一個龐大的物件，裡面的資訊都和使用者登入記錄有關
* session通常儲存在：
  * 記憶體(預設)
  * 資料庫，如MySQL、MongoDB
  * cache，如Redis、Memcached  
* 常見的session攻擊如[session hijacking](https://owasp.org/www-community/attacks/Session_hijacking_attack)，攻擊者竊取session ID並送至伺服器，若伺服器未檢查session ID的使用者身分，即可成功獲取該ID使用者的相關資訊。
* 常見預防session攻擊的措施包含：
  - 增強session ID的長度、隨機性，使攻擊者難以猜測
  - 設置session的有效期限(time-out)
  - 增強cookie的安全性
  - 設置HTTPS-Only

### **Cookie**
Cookie是使用者瀏覽網站時，由伺服器建立，傳送給瀏覽器，並透過加密的方式儲存在用戶端（Client Side）上的小片段文檔(text)。
* Cookies是key-value pair 的結構，儲存session ID，不儲存session data(session data存在資料庫裡，[如圖所示](###Session))，由HTTP response header設置，有效期為直到瀏覽器關閉或cookie過期：
`Set-Cookie: Key=Value`　
實際上看起來像是`Set-Cookie: sessionID=91laR31m`
* Cookies可能會儲存敏感的個人資訊，例如個人偏好或瀏覽紀錄，所以應該確保cookie的安全性，例如透過

  **1. 增加cookie到期時間：**
`Set-Cookie: Key=Value; expires=Monday, 13-March-2023 09:20:10 GMT`
  **2. 增加HttpOnly的特性：**
  透過增加[HttpOnly](https://owasp.org/www-community/HttpOnly)的特性，確保cookie的資料不會因XSS攻擊(Cross-Site Scripting)經由JavaScript直接存取session cookie。
  `Set-Cookie: Key=Value; expires=Monday, 13-March-2023 09:20:10 GMT; HTTPOnly`
  **3. 增加其他特性：**
[SameSite](https://owasp.org/www-community/SameSite)：避免CSRF(Cross-Site Request Forgery)攻擊
[Secure](https://owasp.org/www-community/controls/SecureCookieAttribute)：確保只有https的網站可以獲得cookie的資料 
更多詳情可參考[MDN文件](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#samesitesamesite-value)關於Set-Cookie的解釋

* 通常儲存Cookie的地方包含：**記憶體或硬體**內，記憶體是由瀏覽器來維護的，通常會在瀏覽器關閉後清除，不同瀏覽器間的Cookie無法相互使用；硬體的Cookie則有保存期限，除非過期或是手動刪除，否則儲存時間會較瀏覽器來的久。
### **Session-Cookie運作模式**
1. 使用者進入網站，伺服器產生session和session ID
2. 伺服器的response header中可以Set-Cookie，寫入session id及其他屬性，瀏覽器收到response，儲存一個存有session ID的cookie(但不應包含任何私人資訊)
3. 存放有session ID的cookie自動連結在之後的HTTP request，傳送給伺服器
4. 伺服器接收到含有session ID的cookie的request時，解析session ID並回傳該ID相關連的session資料
5. 只要session 處於active狀態，此過程重複且持續進行
6. 當使用者關掉瀏覽器/登出/超過預先設定的session時限(如:30分鐘)，session和對應的cookie即過期。
### **利用Cookie與Session進行使用者認證**
![](https://i.imgur.com/vsSA0k9.png)<h6 style="text-align:center">(Source: Alpha Camp material)</h6>

* 第一次登入：伺服器建立一個 session :arrow_right: 把 session id 交給用戶端:arrow_right:用戶端把 session id 保存到瀏覽器的 cookie 裡。

* 下一次登入：同一個瀏覽器發送請求:arrow_right:附上同一組 session id:arrow_right:伺服器會判斷「這個 request 來自一個登入過的使用者」:arrow_right:這個瀏覽器可以使用授權的服務內容。

* 登出：把這個 session id 消滅掉:arrow_right:結束這一回合的會話 (session)。下次再進入網站時，又需要重新登入、建立新的 session。

### 使用者認證的安全性

cookie 保存在用戶端，而用戶端可以隨意修改自己的本地資訊。如果認證機制如此單純，使用者就可以修改自己的session id假冒他人登入，因此伺服器當然不可以允許這種事發生，不但資訊本身要加密，session 裡還需要有其他的驗證機制，防止用戶端偷改資訊以及避免資訊外洩。



---

## 參考資料
* Alpha Camp教案
* [Day25 來人上菜! 給我來點Cookie and Session](https://ithelp.ithome.com.tw/articles/10278733)
* [[不是工程師] Cookie 是文檔還是餅乾？簡述HTTP網頁紀錄會員資訊的一大功臣。](https://progressbar.tw/posts/91)
* [深入理解無狀態協議、HTTP 與 web 會話](https://blog.csdn.net/antony1776/article/details/83474496)
* [白話 Session 與 Cookie：從經營雜貨店開始](https://hulitw.medium.com/session-and-cookie-15e47ed838bc)
* [Difference between Stateless and Stateful Protocol](https://www.geeksforgeeks.org/difference-between-stateless-and-stateful-protocol/)

::: success
:crescent_moon: 　本站內容僅為個人學習記錄，如有錯誤歡迎留言告知、交流討論！
:::