Cookie
什麼是cookie?
大多數的網站在你瀏覽後,會在你的電腦記憶體 or 硬碟中留下一些小小的純文字檔案,就是所謂的 Cookie。
$ locate Cookies
....
/home/username/.config/google-chrome/Default/Cookies
....
當你再去瀏覽這些網站時,系統便會去讀取這些 Cookie 檔並且會重新儲存一遍。 透過上述的方式就能夠紀錄上一個request的資訊。而不同的瀏覽器有不同管理 cookie 資料的方法,以 Chrome 為例,他使用 Sqlite (i.e 一個小型的資料庫) 來管理 cookie。
cookie存在的用途及運作方式?
如同前言所述,在網路世界中,client 與 server 間的溝通需透過 HTTP 協定發送 request 和接收 response,但由於 HTTP stateless 的設計,requests 之間是獨立的個體,也就是說 server 端無法記住 client 端發送過哪些請求以此來記住 client 目前的狀態。
為了讓 server 端能記住 client 的狀態,HTTP 利用 Cookie 和 Set-Cookie 這兩個 header 提供 cookies 的功能,以下是 HTTP cookies 的運作方式:
Step1. Client 發送帶有其資料的 request。
Step2. Server 會使用 Set-Cookie header 告訴 browser 這些資料要存在 Cookies 資料庫,當 Chrome 收到帶有 Set-Cookie 的 response 時,會將 Set-Cookie 的 value 存入 Cookies 資料庫 (ex: Crome SQLite database)。
Step3. 接著當Client 透過 Chrome 發送請求到 “test.com” 這個 domain 時,Chrome 會從 Cookies 資料庫中讀取所有關於 “test.com” 這個 domain 的 Cookies 資料,並放在 request 的 Cookie header 中。
Step4. 最後 Server 透過解析 request Cookie header 中的資訊,了解 client 目前的狀態。
cookie與同源政策?
在上述的例子我們可以發現 Chrome 在讀取 Cookie 資料時會根據 request 的目前的 domain name 來找對應的 Cookie 資料,這項行為是受限於-同源政策。
同源政策是用來限制網路資源共享的規則,當網路資源有著相同的 1. 協議 2. 網域 3. 端口 時,這些資源才可以彼此共享。
Cookie的資料屬性?
1. 存在Client端(瀏覽器),安全性較低,但可以加密後存放。
2. 只存在原本的Domain底下。
3. 以key/value方式儲存,儲存時間可以根據需要進行設定:
- 如果沒有設定Cookie失效日期,它的生命週期儲存到關閉瀏覽器
- 若Cookie物件的Expires屬性設定為MinValue,表示永不過期
4. Cookie的資料大小單位是bytes,一個 Cookie最大可以是 4096 bytes,而一個 domain 最多只能有 20 cookies。
5. 由於每次 request 必須將 cookies 的資料放在 headers,所以當 cookies 的資料變大時,request 也會變大,過大的 request 會影響網路傳輸的速度。
Session
Session的發展起因?
Cookies 和 Session 存在的目的都是幫助 Server 記住 Client 的狀態,差別在 Cookies 是將狀態資料存在 Client 端(ex: Browser),而 Session 則是將資料存在 Server 端 (ex: Redis)。
那麼問題來了,這兩個相似的技術有什麼關係呢?其實 Session 並不是用來替代 Cookies ,而是用來彌補 Cookies 的不足
Session存在的用途及運作方式?
為了彌補 Cookies 的不足,我們會在 Server 端使用 Session 的機制去儲存這些狀態資訊,並產生一組 Session key 放入 Cookie 中,由於狀態資訊是直接存在 Server 端的,所以使用者無法讀取,使用者只能看到 session key 但不知道其結構,同時也能避免 Cookie 存入過多資料。
Session-based authentication 是 stateful 的驗證機制,也就是 Server 端和 Client 端都必須儲存狀態資訊,例如 Server 端必須將使用者資料存在 Session database,而Client 端也必須用 Cookie 儲存 session_id。
Step1. Client 發送帶有其資料的 request。
Step2. Server 端的 Session database(ex: mysql or redis)會將使用者資料存起來,並產生一組session _id,透過Set-Cookie header傳給Client端。
Step3. 接著當Client 透過 Chrome 發送請求到 “test.com” 這個 domain 時,Chrome 會從 Cookies 資料庫中讀取所有關於 “test.com” 這個 domain 的 Cookies 資料,並將session_id放在 request 的 Cookie header 中。
Step4. 最後 Server 可以拿到request Cookie header 中的session_id資訊,去session database查找使用者資訊。
Session 限制?
不適用於API-Based 的架構上。
原因是 session_id 必須儲存於 cookie 中,而 cookie 必須遵守同源政策, 也就是說如果Web Server 和 API Server 的 domain 不同,Web Server 無法將 session_id 透過 cookie 傳送給 API server,因此 API Server 也無法驗證使用者的身分。
解決方式?
可以採用Token來解決上述的問題。