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


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

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


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 的過期時間為瀏覽器會話結束;


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


接下來客戶端每次向同一個網站發送請求時,請求頭都會帶上該 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 頭將所有以前存儲的 Cookie 發送回服務器。


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


有兩種類型的 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)外過期。例如

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

Cookie 的 Secure 和 HttpOnly 標記

安全的 Cookie 需要經過 HTTPS 協議通過加密的方式發送到服務器。即使是安全的,也不應該將敏感信息存儲在cookie 中,因為它們本質上是不安全的,並且此標誌不能提供真正的保護。

HttpOnly 的作用

  • 會話 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,則以下地址都會匹配:

  • /docs
  • /docs/Web/
  • /docs/Web/HTTP

JSON Web Token 和 Session Cookies 的對比

JSON Web Token ,簡稱 JWT,它和 Session都可以為網站提供用戶的身份認證,但是它們不是一回事。

下面是 JWT 和 Session 不同之處的研究

JWT 和 Session Cookies 的相同之處

在探討 JWT 和 Session Cookies 之前,有必要需要先去理解一下它們的相同之處。

它們既可以對用戶進行身份驗證,也可以用來在用戶單擊進入不同頁面時以及登陸網站或應用程序後進行身份驗證。

如果沒有這兩者,那你可能需要在每個頁面切換時都需要進行登錄了。因為 HTTP 是一個無狀態的協議。這也就意味著當你訪問某個網頁,然後單擊同一站點上的另一個頁面時,服務器的內存中將不會記住你之前的操作。


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


因此,如果你登錄並訪問了你有權訪問的另一個頁面,由於 HTTP 不會記錄你剛剛登錄的信息,因此你將再次登錄。

JWT 和 Session Cookies 就是用來處理在不同頁面之間切換,保存用戶登錄信息的機制

也就是說,這兩種技術都是用來保存你的登錄狀態,能夠讓你在瀏覽任意受密碼保護的網站。通過在每次產生新的請求時對用戶數據進行身份驗證來解決此問題。

所以 JWT 和 Session Cookies 的相同之處是什麼?那就是它們能夠支持你在發送不同請求之間,記錄並驗證你的登錄狀態的一種機制。

什麼是 Session Cookies

Session Cookies 也稱為會話 Cookies,在 Session Cookies 中,用戶的登錄狀態會保存在服務器的內存中。當用戶登錄時,Session 就被服務端安全的創建。

在每次請求時,服務器都會從會話 Cookie 中讀取 SessionId,如果服務端的數據和讀取的 SessionId 相同,那麼服務器就會發送響應給瀏覽器,允許用戶登錄。


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


什麼是 Json Web Tokens

Json Web Token 的簡稱就是 JWT,通常可以稱為 Json 令牌。它是RFC 7519 中定義的用於安全的將信息作為 Json 對象進行傳輸的一種形式。JWT 中存儲的信息是經過數字簽名的,因此可以被信任和理解。可以使用 HMAC 算法或使用 RSA/ECDSA 的公用/專用密鑰對 JWT 進行簽名。

使用 JWT 主要用來下面兩點

  • 認證(Authorization):這是使用 JWT 最常見的一種情況,一旦用戶登錄,後面每個請求都會包含 JWT,從而允許用戶訪問該令牌所允許的路由、服務和資源。單點登錄是當今廣泛使用 JWT 的一項功能,因為它的開銷很小。
  • 信息交換(Information Exchange):JWT 是能夠安全傳輸信息的一種方式。通過使用公鑰/私鑰對 JWT 進行簽名認證。此外,由於簽名是使用 head 和 payload 計算的,因此你還可以驗證內容是否遭到篡改。

JWT 的格式

下面,我們會探討一下 JWT 的組成和格式是什麼

JWT 主要由三部分組成,每個部分用 . 進行分割,各個部分分別是

  • Header
  • Payload
  • Signature

因此,一個非常簡單的 JWT 組成會是下面這樣


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


然後我們分別對不同的部分進行探討。

Header

Header 是 JWT 的標頭,它通常由兩部分組成:令牌的類型(即 JWT)和使用的 簽名算法,例如 HMAC SHA256 或 RSA。

例如

<code>{ 

"alg": "HS256",
"typ": "JWT"
}/<code>

指定類型和簽名算法後,Json 塊被 Base64Url 編碼形成 JWT 的第一部分。

Payload

Token 的第二部分是 Payload,Payload 中包含一個聲明。聲明是有關實體(通常是用戶)和其他數據的聲明。共有三種類型的聲明:registered, public 和 private 聲明。

  • registered 聲明: 包含一組建議使用的預定義聲明,主要包括

ISS簽發人iss (issuer)簽發人exp (expiration time)過期時間sub (subject)主題aud (audience)受眾nbf (Not Before)生效時間iat (Issued At)簽發時間jti (JWT ID)編號

  • public 聲明:公共的聲明,可以添加任何的信息,一般添加用戶的相關信息或其他業務需要的必要信息,但不建議添加敏感信息,因為該部分在客戶端可解密。
  • private 聲明:自定義聲明,旨在在同意使用它們的各方之間共享信息,既不是註冊聲明也不是公共聲明。

例如

<code>{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}/<code>

然後 payload Json 塊會被Base64Url 編碼形成 JWT 的第二部分。

signature

JWT 的第三部分是一個簽證信息,這個簽證信息由三部分組成

  • header (base64後的)
  • payload (base64後的)
  • secret

比如我們需要 HMAC SHA256 算法進行簽名

<code>HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)/<code>

簽名用於驗證消息在此過程中沒有更改,並且對於使用私鑰進行簽名的令牌,它還可以驗證 JWT 的發送者的真實身份

拼湊在一起

現在我們把上面的三個由點分隔的 Base64-URL 字符串部分組成在一起,這個字符串可以在 HTML 和 HTTP 環境中輕鬆傳遞這些字符串。

下面是一個完整的 JWT 示例,它對 header 和 payload 進行編碼,然後使用 signature 進行簽名

<code>eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
/<code>


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


如果想自己測試編寫的話,可以訪問 JWT 官網 jwt.io/#debugger-i…

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 的面試題......


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


但還是選擇瞭解了一下,如何禁用 Cookies 後,使用 Session

  • 如果禁用了 Cookies,服務器仍會將 sessionId 以 cookie 的方式發送給瀏覽器,但是,瀏覽器不再保存這個cookie (即sessionId) 了。
  • 如果想要繼續使用 session,需要採用 URL 重寫 的方式來實現



分享到:


相關文章: