京東面試:說說Cookie、Session和Token的區別?
東子作為目前傳統電商三巨頭之一(其他還有阿里巴巴和拼多多),其面試題的難度也中規中矩,總體來說沒有其他兩家面試難度高,當然薪資也沒有其他兩家薪資高。
其中拼多多的薪資最為離譜,尤其是前幾年,聽說挖同行的開發人員,薪資可以開到原來薪資的兩到三倍,真是變態(但是我喜歡)。
東子的面試題如下:
圖片
其中大部分面試題可以在我的網站上找到答案(www.javacn.site),這里就不再贅述了。咱們今天只聊:Cookie、Session 和 Token 的區別?
1.Cookie、Session 和 Token 有什么區別?
Cookie、Session 和 Token 通常都是用來保存用戶登錄信息的技術,但三者有很大的區別,簡單來說 Cookie 適用于簡單的狀態管理,Session 適用于需要保護用戶敏感信息的場景,而 Token 適用于狀態無關的身份驗證和授權。
Token 狀態無關性解析:在傳統的基于會話的認證方式中,服務器需要在后端保存用戶的會話狀態,通過 Session ID 進行會話的管理。而 Token 機制不需要在服務器上保存任何關于用戶的狀態信息,只需要在登錄成功時,服務器端通過某種算法生成一個唯一的 Token 值,之后再將此 Token 發送給客戶端存儲(存儲在 localStorage 或 sessionStorage 中),注意此時服務端是不存儲這個 Token 值的,服務器端只進行效驗而不保存此 Token,這就叫“狀態無關性”。這樣就可以減輕服務器存儲和管理會話狀態的負擔,所以它比較適用于大型系統和分布式系統。
具體來說,Cookie、Session 和 Token 的區別主要有以下幾點區別:
- 存儲位置不同:Cookie 存儲在客戶端,即瀏覽器中的文本文件,通過在 HTTP 頭中傳遞給服務器來進行通信;Session 是服務器端的存儲方式,通常存儲在服務器的內存或數據庫中;Token 也是存儲在客戶端,但是通常以加密的方式存儲在客戶端的 localStorage 或 sessionStorage 中。
- 數據安全性不同:Cookie 存儲在客戶端,可能會被竊取或篡改,因此對敏感信息的存儲需要進行加密處理;Session 存儲在服務器端,通過一個 Session ID 在客戶端和服務器之間進行關聯,可以避免敏感數據直接暴露;Token 通常使用加密算法生成,有效期較短且單向不可逆,可以提供較高的安全性。
- 跨域支持不同:為了防止安全事故,因此 Cookie 是不支持跨域傳輸的,也就是不同域名下的 Cookie 是不能相互訪問的;而 Session 機制通常是通過 Cookie 來保存 Session ID 的,因此 Session ID 默認情況下也是不支持跨域的;但 Token 可以輕松實現跨域,因為 Token 是存儲在客戶端的 localStorage 或者作為請求頭的一部分發送到服務器的,所以不同的域名 Token 信息傳輸通常是不受影響的。
- 狀態管理不同:Cookie 是應用程序通過在客戶端存儲臨時數據,用于實現狀態管理的一種機制;Session 是服務器端記錄用戶狀態的方式,服務器會為每個會話分配一個唯一的 Session ID,并將其與用戶狀態相關聯;Token 是一種用于認證和授權的一種機制,通常表示用戶的身份信息和權限信息。
2.Cookie 和 Session 有什么關系?
準確來說 Cookie 的實現和 Session 是沒有任何關系的,但 Session 的實現需要借助于 Cookie。
Session 機制的實現流程如下:
- 會話創建:通常情況下,當用戶登錄成功后,服務器會為該用戶創建一個新的會話。在創建會話過程中,服務器會為該會話生成一個唯一的標識符,通常稱為 Session ID。
- Session ID 傳遞:服務器將生成的 Session ID 通過響應的方式發送給客戶端,使用 SetCookie 命令,將用戶的 Session ID 保存在 Cookie 中,通常是一個名為 JSESSIONID 的 Cookie。
- Session 數據存儲:在服務器端,Session 數據會被存儲在一個能夠關聯 Session ID 的數據結構中(例如內存、數據庫或者文件存儲等)。常用的方式是將 Session ID 作為鍵,與對應的 Session 用戶身份數據進行關聯。
- Session ID 驗證與檢索:當用戶發送一個新的請求時,客戶端會將之前存儲的 Session ID 攜帶在請求的 Cookie 或請求頭中發送給服務器。服務器會根據 Session ID 找到對應的 Session 數據,從而獲得用戶的狀態信息。
- Session 數據使用:服務器在獲取到 Session 數據后,可以根據具體需求讀取、修改或刪除其中保存的狀態信息。服務器可以通過 Session 來管理用戶的登錄狀態、購物車內容、用戶配置等。
- Session 過期與銷毀:Session 有一個有效期限,一般通過設置一個固定的時間,或者在一定時間內沒有用戶活動時會將 Session 標記為過期。當 Session 過期時,服務器會銷毀對應的 Session 數據,釋放內存或其他資源。
所以默認情況下,Session 是借助 Cookie 來完成身份標識的傳遞的,這樣服務器端才能根據 Session ID 和保存的會話信息進行關聯,用于找到某個具體登錄的用戶,所以說:默認情況下,Session 機制是依賴 Cookie 實現的。
3.禁用 Cookie 之后 Session 還能用嗎?
通過上文我們知道,默認情況下 Session 機制是依賴 Cookie 實現的,那么是不是禁用了 Cookie 之后,Session 機制也就無法使用了呢?其實不然。
除了默認情況下,我們可以使用 Cookie 來傳遞 Session ID 之外,我們可以通過一些特殊的手段來自行傳遞 Session ID,以此來擺脫禁用 Cookie 之后 Session 無法使用的情況,例如以下兩種實現手段:
- URL Rewriting:可以在每個請求的 URL 中附加 Session ID 參數。服務器在接收到請求時,解析 URL 中的 Session ID,并與對應的 Session 數據進行關聯。這種方式適用于沒有禁用地址欄中的參數傳遞的情況。
- 隱藏表單字段:可以將 Session ID 作為隱藏表單字段的方式傳遞給服務器。當用戶提交表單時,Session ID 將隨著表單數據一起發送給服務器,服務器據此建立與當前會話的關聯。
通過以上手段都可以將 Session ID 傳遞到服務器端(雖然麻煩點),然后在服務器端,我們再對以上傳遞的 Session ID 進行獲取和映射,這樣就手動完成了傳遞和匹配登錄用戶的工作了,Session 機制也得已繼續使用了。
小結
Cookie、Session 和 Token 通常都是用來保存用戶登錄信息的技術,但三者的區別很大:Cookie 適用于簡單的狀態管理,Session 適用于需要保護用戶敏感信息的場景,而 Token 適用于狀態無關的身份驗證和授權。默認情況下 Session 使用了 Cookie 機制來傳遞 Session ID,但在禁用 Cookie 的情況下,使用特殊的手段依然可以傳遞 Session ID,依然可以繼續使用 Session 機制。而 Token 是不在服務器端保存會話信息的,因此更適用于大型項目和分布式項目。