深度分析:面試90%被問到的 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 的過時時間爲瀏覽器會話結束。跨域

接下來客戶端每次向同一個網站發送請求時,請求頭都會帶上該 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

  • 會話管理

登錄、購物車、遊戲得分或者服務器應該記住的其餘內容session

  • 個性化

用戶偏好、主題或者其餘設置負載均衡

  • 追蹤

記錄和分析用戶行爲性能

Cookie 曾經用於通常的客戶端存儲。雖然這是合法的,由於它們是在客戶端上存儲數據的惟一方法,但現在建議使用現代存儲 API。Cookie 隨每一個請求一塊兒發送,所以它們可能會下降性能(尤爲是對於移動數據鏈接而言)。

建立 Cookie

當接收到客戶端發出的 HTTP 請求時,服務器能夠發送帶有響應的 Set-Cookie 標頭,Cookie 一般由瀏覽器存儲,而後將 Cookie 與 HTTP 標頭一同向服務器發出請求。

Set-Cookie 和 Cookie 標頭

Set-Cookie HTTP 響應標頭將 cookie 從服務器發送到用戶代理。下面是一個發送 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 中,由於它們本質上是不安全的,而且此標誌不能提供真正的保護。

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 是一個無狀態的協議。這也就意味着當你訪問某個網頁,而後單擊同一站點上的另外一個頁面時,服務器的內存中將不會記住你以前的操做。

所以,若是你登陸並訪問了你有權訪問的另外一個頁面,因爲 HTTP 不會記錄你剛剛登陸的信息,所以你將再次登陸。

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

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

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

什麼是 Session Cookies

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

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

什麼是 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 組成會是下面這樣

而後咱們分別對不一樣的部分進行探討。

Header

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

例如

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

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

Payload

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

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

  • public 聲明:公共的聲明,能夠添加任何的信息,通常添加用戶的相關信息或其餘業務須要的必要信息,但不建議添加敏感信息,由於該部分在客戶端可解密。
  • private 聲明:自定義聲明,旨在在贊成使用它們的各方之間共享信息,既不是註冊聲明也不是公共聲明。

例如

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

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

signature

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

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

好比咱們須要 HMAC SHA256 算法進行簽名

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

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

拼湊在一塊兒

如今咱們把上面的三個由點分隔的 Base64-URL 字符串部分組成在一塊兒,這個字符串能夠在 HTML 和 HTTP 環境中輕鬆傳遞這些字符串。

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

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ

    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 顯然更適合。

相關文章
相關標籤/搜索