看完這篇 Session、Cookie、Token,和面試官扯皮就沒問題了

2021-02-20 Java後端


Cookie 和 Session

HTTP 協議是一種無狀態協議,即每次服務端接收到客戶端的請求時,都是一個全新的請求,伺服器並不知道客戶端的歷史請求記錄;Session 和 Cookie 的主要目的就是為了彌補 HTTP 的無狀態特性。

Session 是什麼

客戶端請求服務端,服務端會為這次請求開闢一塊內存空間,這個對象便是 Session 對象,存儲結構為 ConcurrentHashMap。Session 彌補了 HTTP 無狀態特性,伺服器可以利用 Session 存儲客戶端在同一個會話期間的一些操作記錄。

Session 如何判斷是否是同一會話

伺服器第一次接收到請求時,開闢了一塊 Session 空間(創建了Session對象),同時生成一個 sessionId ,並通過響應頭的 Set-Cookie:JSESSIONID=XXXXXXX 命令,向客戶端發送要求設置 Cookie 的響應;客戶端收到響應後,在本機客戶端設置了一個 JSESSIONID=XXXXXXX 的 Cookie 信息,該 Cookie 的過期時間為瀏覽器會話結束。

接下來客戶端每次向同一個網站發送請求時,請求頭都會帶上該 Cookie 信息(包含 sessionId ), 然後,伺服器通過讀取請求頭中的 Cookie 信息,獲取名稱為 JSESSIONID 的值,得到此次請求的 sessionId。

Session 的缺點

Session 機制有個缺點,比如 A 伺服器存儲了 Session,就是做了負載均衡後,假如一段時間內 A 的訪問量激增,會轉發到 B 進行訪問,但是 B 伺服器並沒有存儲 A 的 Session,會導致 Session 的失效。

Cookies 是什麼

HTTP 協議中的 Cookie 包括 Web Cookie 和瀏覽器 Cookie,它是伺服器發送到 Web 瀏覽器的一小塊數據。伺服器發送到瀏覽器的 Cookie,瀏覽器會進行存儲,並與下一個請求一起發送到伺服器。通常,它用於判斷兩個請求是否來自於同一個瀏覽器,例如用戶保持登錄狀態。

HTTP Cookie 機制是 HTTP 協議無狀態的一種補充和改良

Cookie 主要用於下面三個目的

登陸、購物車、遊戲得分或者伺服器應該記住的其他內容Cookie 曾經用於一般的客戶端存儲。雖然這是合法的,因為它們是在客戶端上存儲數據的唯一方法,但如今建議使用現代存儲 API。Cookie 隨每個請求一起發送,因此它們可能會降低性能(尤其是對於移動數據連接而言)。創建 Cookie當接收到客戶端發出的 HTTP 請求時,伺服器可以發送帶有響應的 Set-Cookie 標頭,Cookie 通常由瀏覽器存儲,然後將 Cookie 與 HTTP 標頭一同向伺服器發出請求。Set-Cookie 和 Cookie 標頭Set-Cookie HTTP 響應標頭將 cookie 從伺服器發送到用戶代理。下面是一個發送 Cookie 的例子現在,隨著對伺服器的每個新請求,瀏覽器將使用 Cookie 頭將所有以前存儲的 Cookie 發送回伺服器。有兩種類型的 Cookies,一種是 Session Cookies,一種是 Persistent Cookies,如果 Cookie 不包含到期日期,則將其視為會話 Cookie。會話 Cookie 存儲在內存中,永遠不會寫入磁碟,當瀏覽器關閉時,此後 Cookie 將永久丟失。如果 Cookie 包含有效期 ,則將其視為持久性 Cookie。在到期指定的日期,Cookie 將從磁碟中刪除。還有一種是 Cookie的 Secure 和 HttpOnly 標記,下面依次來介紹一下會話 Cookies上面的示例創建的是會話 Cookie ,會話 Cookie 有個特徵,客戶端關閉時 Cookie 會刪除,因為它沒有指定Expires或 Max-Age 指令。但是,Web 瀏覽器可能會使用會話還原,這會使大多數會話 Cookie 保持永久狀態,就像從未關閉過瀏覽器一樣。永久性 Cookies永久性 Cookie 不會在客戶端關閉時過期,而是在特定日期(Expires)或特定時間長度(Max-Age)外過期。例如

Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT;

Cookie的 Secure 和 HttpOnly 標記安全的 Cookie 需要經過 HTTPS 協議通過加密的方式發送到伺服器。即使是安全的,也不應該將敏感信息存儲在cookie 中,因為它們本質上是不安全的,並且此標誌不能提供真正的保護。會話 Cookie 中缺少 HttpOnly 屬性會導致攻擊者可以通過程序(JS腳本、Applet等)獲取到用戶的 Cookie 信息,造成用戶 Cookie 信息洩露,增加攻擊者的跨站腳本攻擊威脅。HttpOnly 是微軟對 Cookie 做的擴展,該值指定 Cookie 是否可通過客戶端腳本訪問。如果在 Cookie 中沒有設置 HttpOnly 屬性為 true,可能導致 Cookie 被竊取。竊取的 Cookie 可以包含標識站點用戶的敏感信息,如 ASP.NET 會話 ID 或 Forms 身份驗證票證,攻擊者可以重播竊取的 Cookie,以便偽裝成用戶或獲取敏感信息,進行跨站腳本攻擊等。Cookie 的作用域Domain 和 Path 標識定義了 Cookie 的作用域:即 Cookie 應該發送給哪些 URL。Domain 標識指定了哪些主機可以接受 Cookie。如果不指定,默認為當前主機(不包含子域名)。如果指定了Domain,則一般包含子域名。例如,如果設置 Domain=mozilla.org,則 Cookie 也包含在子域名中(如developer.mozilla.org)。例如,設置 Path=/docs,則以下地址都會匹配:JSON Web Token 和 Session Cookies 的對比JSON Web Token ,簡稱 JWT,它和 Session都可以為網站提供用戶的身份認證,但是它們不是一回事。下面是 JWT 和 Session 不同之處的研究JWT 和 Session Cookies 的相同之處在探討 JWT 和 Session Cookies 之前,有必要需要先去理解一下它們的相同之處。它們既可以對用戶進行身份驗證,也可以用來在用戶單擊進入不同頁面時以及登陸網站或應用程式後進行身份驗證。如果沒有這兩者,那你可能需要在每個頁面切換時都需要進行登錄了。因為 HTTP 是一個無狀態的協議。這也就意味著當你訪問某個網頁,然後單擊同一站點上的另一個頁面時,伺服器的內存中將不會記住你之前的操作。因此,如果你登錄並訪問了你有權訪問的另一個頁面,由於 HTTP 不會記錄你剛剛登錄的信息,因此你將再次登錄。JWT 和 Session Cookies 就是用來處理在不同頁面之間切換,保存用戶登錄信息的機制。也就是說,這兩種技術都是用來保存你的登錄狀態,能夠讓你在瀏覽任意受密碼保護的網站。通過在每次產生新的請求時對用戶數據進行身份驗證來解決此問題。所以 JWT 和 Session Cookies 的相同之處是什麼?那就是它們能夠支持你在發送不同請求之間,記錄並驗證你的登錄狀態的一種機制。什麼是 Session CookiesSession Cookies 也稱為會話 Cookies,在 Session Cookies 中,用戶的登錄狀態會保存在伺服器的內存中。當用戶登錄時,Session 就被服務端安全的創建。在每次請求時,伺服器都會從會話 Cookie 中讀取 SessionId,如果服務端的數據和讀取的 SessionId 相同,那麼伺服器就會發送響應給瀏覽器,允許用戶登錄。什麼是 Json Web TokensJson Web Token 的簡稱就是 JWT,通常可以稱為 Json 令牌。它是RFC 7519 中定義的用於安全的將信息作為 Json 對象進行傳輸的一種形式。JWT 中存儲的信息是經過數字籤名的,因此可以被信任和理解。可以使用 HMAC 算法或使用 RSA/ECDSA 的公用/專用密鑰對 JWT 進行籤名。認證(Authorization):這是使用 JWT 最常見的一種情況,一旦用戶登錄,後面每個請求都會包含 JWT,從而允許用戶訪問該令牌所允許的路由、服務和資源。單點登錄是當今廣泛使用 JWT 的一項功能,因為它的開銷很小。信息交換(Information Exchange):JWT 是能夠安全傳輸信息的一種方式。通過使用公鑰/私鑰對 JWT 進行籤名認證。此外,由於籤名是使用 head 和 payload 計算的,因此你還可以驗證內容是否遭到篡改。JWT 的格式JWT 主要由三部分組成,每個部分用 . 進行分割,各個部分分別是Header 是 JWT 的標頭,它通常由兩部分組成:令牌的類型(即 JWT)和使用的 籤名算法,例如 HMAC SHA256 或 RSA。

{
  "alg": "HS256",
  "typ": "JWT"
}

指定類型和籤名算法後,Json 塊被 Base64Url 編碼形成 JWT 的第一部分。Token 的第二部分是 Payload,Payload 中包含一個聲明。聲明是有關實體(通常是用戶)和其他數據的聲明。共有三種類型的聲明:registered, public 和 private 聲明。registered 聲明:包含一組建議使用的預定義聲明,主要包括public 聲明:公共的聲明,可以添加任何的信息,一般添加用戶的相關信息或其他業務需要的必要信息,但不建議添加敏感信息,因為該部分在客戶端可解密。private 聲明:自定義聲明,旨在在同意使用它們的各方之間共享信息,既不是註冊聲明也不是公共聲明。

{
  "sub": "1234567890",
  "name": "John Doe",
  "admin": true
}

然後 payload Json 塊會被Base64Url 編碼形成 JWT 的第二部分。JWT 的第三部分是一個籤證信息,這個籤證信息由三部分組成比如我們需要 HMAC SHA256 算法進行籤名

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret)

籤名用於驗證消息在此過程中沒有更改,並且對於使用私鑰進行籤名的令牌,它還可以驗證 JWT 的發送者的真實身份拼湊在一起現在我們把上面的三個由點分隔的 Base64-URL 字符串部分組成在一起,這個字符串可以在 HTML 和 HTTP 環境中輕鬆傳遞這些字符串。下面是一個完整的 JWT 示例,它對 header 和 payload 進行編碼,然後使用 signature 進行籤名

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ

如果想自己測試編寫的話,可以訪問 JWT 官網 https://jwt.io/#debugger-io    JWT 和 Session Cookies 的不同JWT 和 Session Cookies 都提供安全的用戶身份驗證,但是它們有以下幾點不同密碼籤名JWT 具有加密籤名,而 Session Cookies 則沒有。JSON 是無狀態的JWT 是無狀態的,因為聲明被存儲在客戶端,而不是服務端內存中。身份驗證可以在本地進行,而不是在請求必須通過伺服器資料庫或類似位置中進行。這意味著可以對用戶進行多次身份驗證,而無需與站點或應用程式的資料庫進行通信,也無需在此過程中消耗大量資源。可擴展性Session Cookies 是存儲在伺服器內存中,這就意味著如果網站或者應用很大的情況下會耗費大量的資源。由於 JWT 是無狀態的,在許多情況下,它們可以節省伺服器資源。因此 JWT 要比 Session Cookies 具有更強的可擴展性。JWT 支持跨域認證Session Cookies 只能用在單個節點的域或者它的子域中有效。如果它們嘗試通過第三個節點訪問,就會被禁止。如果你希望自己的網站和其他站點建立安全連接時,這是一個問題。使用 JWT 可以解決這個問題,使用 JWT 能夠通過多個節點進行用戶認證,也就是我們常說的跨域認證。JWT 和 Session Cookies 的選型我們上面探討了 JWT 和 Cookies 的不同點,相信你也會對選型有了更深的認識,大致來說對於只需要登錄用戶並訪問存儲在站點資料庫中的一些信息的中小型網站來說,Session Cookies 通常就能滿足。如果你有企業級站點,應用程式或附近的站點,並且需要處理大量的請求,尤其是第三方或很多第三方(包括位於不同域的API),則 JWT 顯然更適合。後記前兩天面試的時候問到了這個題,所以寫篇文章總結一下,還問到了一個面試題,禁用 Cookies,如何使用 Session ?網上百度了一下,發現這是 PHP 的面試題,em但還是選擇了解了一下,如何禁用 Cookies 後,使用 Session
如果禁用了 Cookies,伺服器仍會將 sessionId 以 cookie 的方式發送給瀏覽器,但是,瀏覽器不再保存這個cookie (即sessionId) 了。如果想要繼續使用 session,需要採用 URL 重寫 的方式來實現,可以參考 https://www.cnblogs.com/Renyi-Fan/p/11012086.htmlhttps://www.cnblogs.com/Renyi-Fan/p/11012086.htmlhttps://blog.csdn.net/qq_28296925/article/details/80921585https://www.cnblogs.com/-ROCKS/p/6108556.htmlhttps://www.allaboutcookies.org/manage-cookies/https://www.jianshu.com/p/4a124a10fcafhttps://tools.ietf.org/html/rfc7519https://jwt.io/introduction/https://wp-rocket.me/blog/browser-cache-vs-cookies-difference/https://wp-rocket.me/blog/difference-json-web-tokens-vs-session-cookies/

 

如果看到這裡,說明你喜歡這篇文章,請轉發、點讚。同時標星(置頂)本公眾號可以第一時間接受到博文推送。

相關焦點

  • 面試必問:session,cookie和token的區別
    session,cookie和token究竟是什麼簡述cookie,
  • 徹底理解Cookie,Session,Token
    比如說, 小F已經登錄了系統, 我給他發一個令牌(token), 裡邊包含了小F的 user id, 下一次小F 再次通過Http 請求訪問我的時候, 把這個token 通過Http header 帶過來不就可以了。不過這和session id沒有本質區別啊, 任何人都可以可以偽造, 所以我得想點兒辦法, 讓別人偽造不了。
  • 面試官:要不講講 Cookie、Session、Token、JWT之間的區別?
    常見問題使用 cookie 時需要考慮的問題因為存儲在客戶端,容易被客戶端篡改,使用前需要驗證合法性不要存儲敏感數據,比如用戶密碼,帳戶餘額使用 httpOnly 在一定程度上提高安全性儘量減少 cookie 的體積,能存儲的數據量不能超過 4kb設置正確的 domain 和 path,減少數據傳輸cookie
  • 前後端接口鑑權全解 Cookie/Session/Token 的區別
    本文主要解釋與請求狀態相關的術語(cookie、session、token)和幾種常見登錄的實現方式,希望大家看完本文後可以有比較清晰的理解,有感到迷惑的地方可以點擊閱讀原文在評論區提出~Cookie眾所周知,http 是無狀態協議,瀏覽器和伺服器不可能憑協議的實現辨別請求的上下文
  • Cookie, Session, Token,WebStorage你懂多少?
    LocalStorage.問題解決了,但是個人覺得很有意思,平常司空見慣的,覺得"假大空不接地氣"的概念,其實都真真切切的在項目中體現了,只不過我們熟生輕視,看不見而已.遂記錄本文.面試的時候經常喜歡問一個問題,HTTP協議是有狀態的還是無狀態的?很多同學都不知道,或者簡單背一個答案,曰無狀態.再問,那麼HTTP協議如何保持狀態?只有一小部分同學能答出來要用cookie和session.再問,有了cookie為什麼還要session?更少一部分人能答出來安全。再問,不要cookie行不行?能答出URL重寫的已經不錯了。
  • 詳解 Cookie,Session,Token
    本文主要講解cookie,session, token 這三種是如何管理會話的;cookiecookie 是一個非常具體的東西,指的就是瀏覽器裡面能永久存儲的一種數據。跟伺服器沒啥關係,僅僅是瀏覽器實現的一種數據存儲功能。
  • Cookie、Session、Token與JWT解析
    另外需要注意的是 token 一般是放在 header 的 Authorization 自定義頭裡,不是放在 Cookie 裡的,這主要是為了解決跨域不能共享 Cookie 的問題總結:token解決什麼問題(為什麼要用token)?
  • cookie、session、token區別
    token,session,cookie的概念和區別1.token是 服務經過計算發給客戶端的,服務不保存,每次客戶端來請求,經過解密等計算來驗證是否是自己下發的2.session是服務本地保存,發給客戶端,客戶端每次訪問都帶著,直接和服務的session比對3.cookie是保存在客戶端上的一些基本信息,服務不保存,每次請求時客戶端帶上cookie,裡面有一些帳戶密碼
  • 徹底理解 cookie、session、token:15 篇前端熱文回看
    其中有技術分享和技術資訊。註:以下文章,點擊標題即可閱讀《徹底理解 cookie、session、token》很久很久以前,Web 基本上就是文檔的瀏覽而已, 既然是瀏覽,作為伺服器, 不需要記錄誰在某一段時間裡都瀏覽了什麼文檔,每次請求都是一個新的HTTP協議, 就是請求加響應, 尤其是我不用記住是誰剛剛發了HTTP請求, 每個請求對我來說都是全新的。
  • Session/Cookie/Token 還傻傻分不清?
    token 的介紹有誤,所以對 cookie,session, token 作了一下對比(文中token指jwt token)相信大家看完肯定有收穫!session 的痛點看起來通過  cookie + session 的方式是解決了問題, 但是我們忽略了一個問題,上述情況能正常工作是因為我們假設 server 是單機工作的,但實際在生產上,為了保障高可用,一般伺服器至少需要兩臺機器,通過負載均衡的方式來決定到底請求該打到哪臺機器上。
  • 一文帶你徹底搞懂Cookie、Session和Token
    1、反向代理hash一致性這類方法是使用Nginx的負載均衡算法其中的hash_ip算法將ip固定到某一臺伺服器上,這樣就不會出現session共享問題,因為同一個ip訪問下,永遠是同一個伺服器。客戶端後續請求都帶上這個token,伺服器首先校驗token是否被篡改(根據hash籤名校驗),如果沒被篡改而且token也沒過期,就把token中的用戶信息(可能還有權限信息等等)拿出來,直接使用,不需要像session一樣去查詢具體用戶信息。
  • 一文讀懂Cookie、Session、Token和JWT(建議收藏)
    常見問題使用 cookie 時需要考慮的問題因為存儲在客戶端,容易被客戶端篡改,使用前需要驗證合法性不要存儲敏感數據,比如用戶密碼,帳戶餘額使用 httpOnly 在一定程度上提高安全性儘量減少 cookie 的體積,能存儲的數據量不能超過 4kb設置正確的 domain 和 path,減少數據傳輸cookie 無法跨域
  • 黑客都知道的Cookie、Session、Token、JWT
    常見問題使用 cookie 時需要考慮的問題因為存儲在客戶端,容易被客戶端篡改,使用前需要驗證合法性不要存儲敏感數據,比如用戶密碼,帳戶餘額使用 httpOnly 在一定程度上提高安全性儘量減少 cookie 的體積,能存儲的數據量不能超過 4kb設置正確的 domain 和 path,減少數據傳輸cookie
  • Cookie、Session、Token、JWT終於講清楚了
    domain 和 path,減少數據傳輸cookie 無法跨域一個瀏覽器針對一個網站最多存 20 個Cookie,瀏覽器一般只允許存放 300 個Cookie移動端對 cookie 的支持不是很好,而 session 需要基於 cookie 實現,所以移動端常用的是 token
  • 熬夜徹底搞懂Cookie Session Token JWT
    就是說這一次請求和上一次請求是沒有任何關係的,互不認識的,沒有關聯的。看過電影《夏洛特煩惱》的小夥伴肯定記得夏洛和大爺的一段對話:夏洛:大爺,樓上322住的是馬冬梅家嗎?大爺:馬冬什麼?夏洛:馬冬梅。大爺:什麼冬梅啊?夏洛:馬冬梅啊。大爺:馬什麼梅啊?
  • 前端鑑權 5 兄弟:cookie、session、token、jwt、單點登錄
    本文你將看到:基於 HTTP 的前端鑑權背景cookie 為什麼是最方便的存儲方案,有哪些操作 cookie 的方式session 方案是如何實現的,存在哪些問題token 方案是如何實現的,如何進行編碼和防篡改?jwt 是做什麼的?
  • 測開之Cookie、Session、Token、JWT的區別
    >cookie 無法跨域一個瀏覽器針對一個網站最多存 20 個Cookie,瀏覽器一般只允許存放 300 個Cookie移動端對 cookie 的支持不是很好,而 session 需要基於 cookie 實現,所以移動端常用的是 token使用 session 時需要考慮的問題
  • 面試官:什麼是CSRF?(你的錢為什麼被轉走,這篇文章告訴你答案)
    這段時間很多文章標題都是面試官,所以跟個風,這篇文章也以面試官開頭,主要內容是關於CSRF。
  • 前端鑑權必須了解的 5 個兄弟:cookie、session、token、jwt、單點登錄
    為什麼是最方便的存儲方案,有哪些操作 cookie 的方式session 方案是如何實現的,存在哪些問題token 方案是如何實現的,如何進行編碼和防篡改?給req提供了session屬性,控制屬性的set/get並響應到cookie和session存取上,並給req.session提供了一些方法。應用方案:tokensession 的維護給服務端造成很大困擾,我們必須找地方存放它,又要考慮分布式的問題,甚至要單獨為了它啟用一套 Redis 集群。有沒有更好的辦法?
  • 還傻傻分不清 Cookie、Session、Token、JWT?
    domain 和 path,減少數據傳輸cookie 無法跨域一個瀏覽器針對一個網站最多存 20 個Cookie,瀏覽器一般只允許存放 300 個Cookie移動端對 cookie 的支持不是很好,而 session 需要基於 cookie 實現,所以移動端常用的是 token