HTTP 協議是一種無狀態協議
,即每次服務端接收到客戶端的請求時,都是一個全新的請求,服務器並不知道客戶端的歷史請求記錄;Session 和 Cookie 的主要目的就是爲了彌補 HTTP 的無狀態特性。算法
客戶端請求服務端,服務端會爲此次請求開闢一塊內存空間
,這個對象即是 Session 對象,存儲結構爲 ConcurrentHashMap
。Session 彌補了 HTTP 無狀態特性,服務器能夠利用 Session 存儲客戶端在同一個會話期間的一些操做記錄。數據庫
服務器第一次接收到請求時,開闢了一塊 Session 空間(建立了Session對象),同時生成一個 sessionId ,並經過響應頭的 Set-Cookie:JSESSIONID=XXXXXXX 命令,向客戶端發送要求設置 Cookie 的響應;客戶端收到響應後,在本機客戶端設置了一個 JSESSIONID=XXXXXXX 的 Cookie 信息,該 Cookie 的過時時間爲瀏覽器會話結束。跨域
接下來客戶端每次向同一個網站發送請求時,請求頭都會帶上該 Cookie 信息(包含 sessionId ), 而後,服務器經過讀取請求頭中的 Cookie 信息,獲取名稱爲 JSESSIONID 的值,獲得這次請求的 sessionId。瀏覽器
Session 機制有個缺點,好比 A 服務器存儲了 Session,就是作了負載均衡後,假如一段時間內 A 的訪問量激增,會轉發到 B 進行訪問,可是 B 服務器並無存儲 A 的 Session,會致使 Session 的失效。安全
HTTP 協議中的 Cookie 包括 Web Cookie
和瀏覽器 Cookie
,它是服務器發送到 Web 瀏覽器的一小塊數據。服務器發送到瀏覽器的 Cookie,瀏覽器會進行存儲,並與下一個請求一塊兒發送到服務器。一般,它用於判斷兩個請求是否來自於同一個瀏覽器,例如用戶保持登陸狀態。服務器
HTTP Cookie 機制是 HTTP 協議無狀態的一種補充和改良
Cookie 主要用於下面三個目的cookie
會話管理
登錄、購物車、遊戲得分或者服務器應該記住的其餘內容session
個性化
用戶偏好、主題或者其餘設置負載均衡
追蹤
記錄和分析用戶行爲性能
Cookie 曾經用於通常的客戶端存儲。雖然這是合法的,由於它們是在客戶端上存儲數據的惟一方法,但現在建議使用現代存儲 API。Cookie 隨每一個請求一塊兒發送,所以它們可能會下降性能(尤爲是對於移動數據鏈接而言)。
當接收到客戶端發出的 HTTP 請求時,服務器能夠發送帶有響應的 Set-Cookie
標頭,Cookie 一般由瀏覽器存儲,而後將 Cookie 與 HTTP 標頭一同向服務器發出請求。
Set-Cookie
HTTP 響應標頭將 cookie 從服務器發送到用戶代理。下面是一個發送 Cookie 的例子
此標頭告訴客戶端存儲 Cookie
如今,隨着對服務器的每一個新請求,瀏覽器將使用 Cookie 頭將全部之前存儲的 Cookie 發送回服務器。
有兩種類型的 Cookies,一種是 Session Cookies,一種是 Persistent Cookies,若是 Cookie 不包含到期日期,則將其視爲會話 Cookie。會話 Cookie 存儲在內存中,永遠不會寫入磁盤,當瀏覽器關閉時,此後 Cookie 將永久丟失。若是 Cookie 包含有效期
,則將其視爲持久性 Cookie。在到期指定的日期,Cookie 將從磁盤中刪除。
還有一種是 Cookie的 Secure 和 HttpOnly 標記
,下面依次來介紹一下
上面的示例建立的是會話 Cookie ,會話 Cookie 有個特徵,客戶端關閉時 Cookie 會刪除,由於它沒有指定Expires
或 Max-Age
指令。
可是,Web 瀏覽器可能會使用會話還原,這會使大多數會話 Cookie 保持永久狀態,就像從未關閉過瀏覽器同樣。
永久性 Cookie 不會在客戶端關閉時過時,而是在特定日期(Expires)
或特定時間長度(Max-Age)
外過時。例如
Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT;
安全的 Cookie 須要通過 HTTPS 協議經過加密的方式發送到服務器。即便是安全的,也不該該將敏感信息存儲在cookie 中,由於它們本質上是不安全的,而且此標誌不能提供真正的保護。
HttpOnly 的做用
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 ,簡稱 JWT
,它和 Session
均可覺得網站提供用戶的身份認證,可是它們不是一回事。
下面是 JWT 和 Session 不一樣之處的研究
在探討 JWT 和 Session Cookies 以前,有必要須要先去理解一下它們的相同之處。
它們既能夠對用戶進行身份驗證,也能夠用來在用戶單擊進入不一樣頁面時以及登錄網站或應用程序後進行身份驗證。
若是沒有這二者,那你可能須要在每一個頁面切換時都須要進行登陸了。由於 HTTP 是一個無狀態的協議。這也就意味着當你訪問某個網頁,而後單擊同一站點上的另外一個頁面時,服務器的內存中
將不會記住你以前的操做。
所以,若是你登陸並訪問了你有權訪問的另外一個頁面,因爲 HTTP 不會記錄你剛剛登陸的信息,所以你將再次登陸。
JWT 和 Session Cookies 就是用來處理在不一樣頁面之間切換,保存用戶登陸信息的機制。
也就是說,這兩種技術都是用來保存你的登陸狀態,可以讓你在瀏覽任意受密碼保護的網站。經過在每次產生新的請求時對用戶數據進行身份驗證來解決此問題。
因此 JWT 和 Session Cookies 的相同之處是什麼?那就是它們可以支持你在發送不一樣請求之間,記錄並驗證你的登陸狀態的一種機制。
Session Cookies 也稱爲會話 Cookies
,在 Session Cookies 中,用戶的登陸狀態會保存在服務器
的內存
中。當用戶登陸時,Session 就被服務端安全的建立。
在每次請求時,服務器都會從會話 Cookie 中讀取 SessionId,若是服務端的數據和讀取的 SessionId 相同,那麼服務器就會發送響應給瀏覽器,容許用戶登陸。
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 主要由三部分組成,每一個部分用 .
進行分割,各個部分分別是
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 的第三部分是一個簽證信息,這個簽證信息由三部分組成
好比咱們須要 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 是存儲在服務器內存中,這就意味着若是網站或者應用很大的狀況下會耗費大量的資源。因爲 JWT 是無狀態的,在許多狀況下,它們能夠節省服務器資源。所以 JWT 要比 Session Cookies 具備更強的可擴展性
。
Session Cookies 只能用在單個節點的域
或者它的子域
中有效。若是它們嘗試經過第三個節點訪問,就會被禁止。若是你但願本身的網站和其餘站點創建安全鏈接時,這是一個問題。
使用 JWT 能夠解決這個問題,使用 JWT 可以經過多個節點
進行用戶認證,也就是咱們常說的跨域認證
。
咱們上面探討了 JWT 和 Cookies 的不一樣點,相信你也會對選型有了更深的認識,大體來講
對於只須要登陸用戶並訪問存儲在站點數據庫中的一些信息的中小型網站來講,Session Cookies 一般就能知足。
若是你有企業級站點,應用程序或附近的站點,而且須要處理大量的請求,尤爲是第三方或不少第三方(包括位於不一樣域的API),則 JWT 顯然更適合。