# Session & Cookie Http 是沒有狀態的,所以每個Request都是不相關的。 Session 是一種讓 Request 變成有狀態的機制,讓瀏覽器和伺服器能互相關聯。而常見實作 Session的一種方法就是 Cookie。 <!-- more --> ![Session & Cookie](https://www.itread01.com/uploads/images/20180928/1538098242-1709.jpg) ## Session Session 是一個暫存的檔案,通常是用來儲存暫時性的資料,比如說使用者的登入狀態,因為 Http 是沒有狀態性的,對於每個 Request 都視是為新的,所以可以透過 Session 紀錄來比對發送 Request 的是誰 流程 : 1. 瀏覽器傳送了一個 Request 到 Server 2. Server 將 Request 所提供的資訊(網址所夾帶的參數、Session Id)儲存到 Server 端的暫存檔 ## 實作Session的方法 實作 Session 有兩種常見的方式,分別為 Cookie 和 URL。 ### 1. Cookie Cookie 是實作 Session 的一種方式,用來儲存少量的特定資料,資料不存在 Server 端的暫存檔,而是放在 Cookie 裡面並存在用戶端的瀏覽器,當瀏覽器和 Server 互動時會隨著 Request 和 Response 來回傳送 通常 Session 都會搭配 Cookie 使用來更方便的紀錄資訊。如果只選用其中一個就會有一些問題,例如 : * 只用 Session : 只會在用戶端儲存一個 Session Id,當用戶關閉了瀏覽器(分頁)時,Session Id 就會不見 * 只用 Cookie : 所有資訊都會存在用戶端,一旦資料量大時用戶端可能沒有這麼多空間可以儲存,另外若是用戶端電腦遭到駭客竊取,所有的資料都會曝光 流程 : 1. Server 收到 Request 後會要求瀏覽器設定一個 Cookie,而這個 Cookie 會儲存一些 Server 要求紀錄的資料,例如 : 一組識別碼用來識別用戶, SessionId, 網址中所夾帶的參數,等等。 2. 下次瀏覽器要再發送 Request 給這個 Server 時,便會帶著 Cookie 發送給 Server,Server 就可以根據 Cookie 的內容來決定狀態 ### 2. URL Server 根據 Request 內的參數將用戶導向到新的網址,現今考量網路安全大多不用此方法 以下由購物網站作為範例 流程 : 1. Server 收到一個 Request 之後,將其所提供的參數擷取出來 > market.com.tw?tmp=apple 2. Server 將提供的參數放進新的網址中 > market.com.tw?item1=apple > apple 被擷取出來放進新的網址中 3. Server 將用戶導向新的網址中 4. 瀏覽器再次發送 Request 時便會多了新的參數,Server 便可以再需要這些資訊的時候從網址中取得 > market.com.tw?item1=apple&tmp=orange > 瀏覽器加入了新的參數 tmp > market.com.tw?item1=apple&item2=orange > orange 被擷取出來放進新的網址中 > market.com.tw?item1=apple&item2=orange&submit=true > 瀏覽器加入了新的參數 submit,代表 Server 可以去處理這些資料了,此時網址裡就有紀錄了 item1, item2 ## 將 Session 儲存到資料庫 Session 是一個暫存檔,而這個暫存檔會造成以下幾個問題 : * 大部分大流量的網站會部署在多台主機上,若是只暫存在某台主機上,下次用戶被導向到其他台主機會找不到之前的 Session 暫存檔 * 若每次 Request 都存到 Server 暫存檔會造成 Server 負擔太大 因此可以將 Session 所需要紀錄的資料存到資料庫便可以解決上述問題。 然而每次都要進資料庫讀取也會有速度上的問題,於是便衍生出了記憶體內的資料庫來提升效能,最常見的是 Redis。想進一步了解什麼是 Redis 以及 Redis 的運作方式請參考本站的 [Redis 系列文章](https://tienyulin.github.io/redis-concept-docker-install-datatype/)。 ## 兩種常見的登入驗證方式 ### Cookie-based Authentication 這是一種很常見的驗證方式,利用 Cookie 傳送 Session Id,但是若 Cookie 在途中被攔截,用戶很容易遭受到偽造的 Request 攻擊 流程 : 1. 瀏覽器發送帳號密碼到 Server 2. Server 驗證帳號密碼成功後便產生一組Session Id放在資料庫 3. Server 將 Session Id 放入 Cookie 後回傳給瀏覽器 4. 下次進入網站時,Request 中 Cookie 的Session Id 會一併傳給 Server,若是 Session Id 有效(包含時效),則會繼續處理這個 Request 5. 當用戶登出時需將資料庫和 Cookie 內的 Session Id 清除 ### Token-based Authentication 類似於 Cookie-based 的流程,但是 Server 會在 Response 時回傳一組加密的Token,以提高安全性。加密的 Token 可以參考 [Json Web Token](https://tienyulin.github.io/json-web-token-jwt/)的介紹。 流程 : 1. 瀏覽器發送帳號密碼到 Server 2. Server 驗證帳號密碼成功後便產生一組加密 Token 放在資料庫 3. Server 將 Token 放入 Cookie 後回傳給瀏覽器 4. 下次進入網站時,Request 中 Cookie 的 Token 會一併傳給 Server,Server 會將 Token 解開做驗證,若驗證成功則繼續處理 Request ## 參考 [1] [白話 Session 與 Cookie:從經營雜貨店開始](https://medium.com/@hulitw/session-and-cookie-15e47ed838bc) [2] [How To Work With Session And Cookies In CodeIgniter](https://techbriefers.com/how-to-work-with-session-and-cookies-in-codeigniter/) [3] [session、cookie and token | iT邦幫忙](https://ithelp.ithome.com.tw/articles/10224935) ###### tags: `Web` `Http` `Cookie` `Session`