Cookie 和 Session
HTTP 協(xié)議是一種無狀態(tài)協(xié)議
熊赖,即每次服務(wù)端接收到客戶端的請求時,都是一個全新的請求虑椎,服務(wù)器并不知道客戶端的歷史請求記錄震鹉;Session 和 Cookie 的主要目的就是為了彌補 HTTP 的無狀態(tài)特性。
Session 是什么
客戶端請求服務(wù)端捆姜,服務(wù)端會為這次請求開辟一塊內(nèi)存空間
传趾,這個對象便是 Session 對象,存儲結(jié)構(gòu)為 ConcurrentHashMap
泥技。Session 彌補了 HTTP 無狀態(tài)特性浆兰,服務(wù)器可以利用 Session 存儲客戶端在同一個會話期間的一些操作記錄。
Session 如何判斷是否是同一會話
服務(wù)器第一次接收到請求時零抬,開辟了一塊 Session 空間(創(chuàng)建了Session對象)镊讼,同時生成一個 sessionId ,并通過響應(yīng)頭的 Set-Cookie:JSESSIONID=XXXXXXX 命令平夜,向客戶端發(fā)送要求設(shè)置 Cookie 的響應(yīng)蝶棋;客戶端收到響應(yīng)后,在本機客戶端設(shè)置了一個 JSESSIONID=XXXXXXX 的 Cookie 信息忽妒,該 Cookie 的過期時間為瀏覽器會話結(jié)束玩裙。
接下來客戶端每次向同一個網(wǎng)站發(fā)送請求時,請求頭都會帶上該 Cookie 信息(包含 sessionId )段直, 然后吃溅,服務(wù)器通過讀取請求頭中的 Cookie 信息,獲取名稱為 JSESSIONID 的值鸯檬,得到此次請求的 sessionId决侈。
Session 的缺點
Session 機制有個缺點,比如 A 服務(wù)器存儲了 Session喧务,就是做了負(fù)載均衡后赖歌,假如一段時間內(nèi) A 的訪問量激增枉圃,會轉(zhuǎn)發(fā)到 B 進行訪問,但是 B 服務(wù)器并沒有存儲 A 的 Session庐冯,會導(dǎo)致 Session 的失效孽亲。
Cookies 是什么
HTTP 協(xié)議中的 Cookie 包括 Web Cookie
和瀏覽器 Cookie
,它是服務(wù)器發(fā)送到 Web 瀏覽器的一小塊數(shù)據(jù)展父。服務(wù)器發(fā)送到瀏覽器的 Cookie返劲,瀏覽器會進行存儲,并與下一個請求一起發(fā)送到服務(wù)器栖茉。通常篮绿,它用于判斷兩個請求是否來自于同一個瀏覽器,例如用戶保持登錄狀態(tài)衡载。
HTTP Cookie 機制是 HTTP 協(xié)議無狀態(tài)的一種補充和改良
Cookie 主要用于下面三個目的
會話管理
登陸搔耕、購物車、游戲得分或者服務(wù)器應(yīng)該記住的其他內(nèi)容
個性化
用戶偏好痰娱、主題或者其他設(shè)置
追蹤
記錄和分析用戶行為
Cookie 曾經(jīng)用于一般的客戶端存儲弃榨。雖然這是合法的,因為它們是在客戶端上存儲數(shù)據(jù)的唯一方法梨睁,但如今建議使用現(xiàn)代存儲 API鲸睛。Cookie 隨每個請求一起發(fā)送,因此它們可能會降低性能(尤其是對于移動數(shù)據(jù)連接而言)坡贺。
創(chuàng)建 Cookie
當(dāng)接收到客戶端發(fā)出的 HTTP 請求時官辈,服務(wù)器可以發(fā)送帶有響應(yīng)的 Set-Cookie
標(biāo)頭,Cookie 通常由瀏覽器存儲遍坟,然后將 Cookie 與 HTTP 標(biāo)頭一同向服務(wù)器發(fā)出請求拳亿。
Set-Cookie 和 Cookie 標(biāo)頭
Set-Cookie
HTTP 響應(yīng)標(biāo)頭將 cookie 從服務(wù)器發(fā)送到用戶代理。下面是一個發(fā)送 Cookie 的例子
此標(biāo)頭告訴客戶端存儲 Cookie
現(xiàn)在愿伴,隨著對服務(wù)器的每個新請求肺魁,瀏覽器將使用 Cookie 頭將所有以前存儲的 Cookie 發(fā)送回服務(wù)器。
有兩種類型的 Cookies隔节,一種是 Session Cookies鹅经,一種是 Persistent Cookies,如果 Cookie 不包含到期日期怎诫,則將其視為會話 Cookie瘾晃。會話 Cookie 存儲在內(nèi)存中,永遠不會寫入磁盤幻妓,當(dāng)瀏覽器關(guān)閉時蹦误,此后 Cookie 將永久丟失。如果 Cookie 包含有效期
,則將其視為持久性 Cookie强胰。在到期指定的日期尚镰,Cookie 將從磁盤中刪除。
還有一種是 Cookie的 Secure 和 HttpOnly 標(biāo)記
哪廓,下面依次來介紹一下
會話 Cookies
上面的示例創(chuàng)建的是會話 Cookie ,會話 Cookie 有個特征初烘,客戶端關(guān)閉時 Cookie 會刪除涡真,因為它沒有指定Expires
或 Max-Age
指令。
但是肾筐,Web 瀏覽器可能會使用會話還原哆料,這會使大多數(shù)會話 Cookie 保持永久狀態(tài),就像從未關(guān)閉過瀏覽器一樣吗铐。
永久性 Cookies
永久性 Cookie 不會在客戶端關(guān)閉時過期东亦,而是在特定日期(Expires)
或特定時間長度(Max-Age)
外過期。例如
Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT;
Cookie的 Secure 和 HttpOnly 標(biāo)記
安全的 Cookie 需要經(jīng)過 HTTPS 協(xié)議通過加密的方式發(fā)送到服務(wù)器唬渗。即使是安全的典阵,也不應(yīng)該將敏感信息存儲在cookie 中,因為它們本質(zhì)上是不安全的镊逝,并且此標(biāo)志不能提供真正的保護壮啊。
HttpOnly 的作用
會話 Cookie 中缺少 HttpOnly 屬性會導(dǎo)致攻擊者可以通過程序(JS腳本、Applet等)獲取到用戶的 Cookie 信息撑蒜,造成用戶 Cookie 信息泄露歹啼,增加攻擊者的跨站腳本攻擊威脅。
HttpOnly 是微軟對 Cookie 做的擴展座菠,該值指定 Cookie 是否可通過客戶端腳本訪問狸眼。
如果在 Cookie 中沒有設(shè)置 HttpOnly 屬性為 true,可能導(dǎo)致 Cookie 被竊取浴滴。竊取的 Cookie 可以包含標(biāo)識站點用戶的敏感信息拓萌,如 ASP.NET 會話 ID 或 Forms 身份驗證票證,攻擊者可以重播竊取的 Cookie巡莹,以便偽裝成用戶或獲取敏感信息司志,進行跨站腳本攻擊等。
Cookie 的作用域
Domain
和 Path
標(biāo)識定義了 Cookie 的作用域:即 Cookie 應(yīng)該發(fā)送給哪些 URL降宅。
Domain
標(biāo)識指定了哪些主機可以接受 Cookie骂远。如果不指定,默認(rèn)為當(dāng)前主機(不包含子域名)腰根。如果指定了Domain
激才,則一般包含子域名。
例如,如果設(shè)置 Domain=mozilla.org
瘸恼,則 Cookie 也包含在子域名中(如developer.mozilla.org
)劣挫。
例如,設(shè)置 Path=/docs
东帅,則以下地址都會匹配:
/docs
/docs/Web/
/docs/Web/HTTP
JSON Web Token 和 Session Cookies 的對比
JSON Web Token 压固,簡稱 JWT
,它和 Session
都可以為網(wǎng)站提供用戶的身份認(rèn)證靠闭,但是它們不是一回事帐我。
下面是 JWT 和 Session 不同之處的研究
JWT 和 Session Cookies 的相同之處
在探討 JWT 和 Session Cookies 之前,有必要需要先去理解一下它們的相同之處愧膀。
它們既可以對用戶進行身份驗證拦键,也可以用來在用戶單擊進入不同頁面時以及登陸網(wǎng)站或應(yīng)用程序后進行身份驗證。
如果沒有這兩者檩淋,那你可能需要在每個頁面切換時都需要進行登錄了芬为。因為 HTTP 是一個無狀態(tài)的協(xié)議。這也就意味著當(dāng)你訪問某個網(wǎng)頁蟀悦,然后單擊同一站點上的另一個頁面時媚朦,服務(wù)器的內(nèi)存中
將不會記住你之前的操作。
因此熬芜,如果你登錄并訪問了你有權(quán)訪問的另一個頁面莲镣,由于 HTTP 不會記錄你剛剛登錄的信息,因此你將再次登錄涎拉。
JWT 和 Session Cookies 就是用來處理在不同頁面之間切換瑞侮,保存用戶登錄信息的機制。
也就是說鼓拧,這兩種技術(shù)都是用來保存你的登錄狀態(tài)半火,能夠讓你在瀏覽任意受密碼保護的網(wǎng)站。通過在每次產(chǎn)生新的請求時對用戶數(shù)據(jù)進行身份驗證來解決此問題季俩。
所以 JWT 和 Session Cookies 的相同之處是什么钮糖?那就是它們能夠支持你在發(fā)送不同請求之間,記錄并驗證你的登錄狀態(tài)的一種機制酌住。
什么是 Session Cookies
Session Cookies 也稱為會話 Cookies
店归,在 Session Cookies 中,用戶的登錄狀態(tài)會保存在服務(wù)器
的內(nèi)存
中酪我。當(dāng)用戶登錄時消痛,Session 就被服務(wù)端安全的創(chuàng)建。
在每次請求時都哭,服務(wù)器都會從會話 Cookie 中讀取 SessionId秩伞,如果服務(wù)端的數(shù)據(jù)和讀取的 SessionId 相同逞带,那么服務(wù)器就會發(fā)送響應(yīng)給瀏覽器,允許用戶登錄纱新。
什么是 Json Web Tokens
Json Web Token 的簡稱就是 JWT展氓,通常可以稱為 Json 令牌
脸爱。它是RFC 7519
中定義的用于安全的
將信息作為 Json 對象
進行傳輸?shù)囊环N形式遇汞。JWT 中存儲的信息是經(jīng)過數(shù)字簽名
的,因此可以被信任和理解簿废∩滋郏可以使用 HMAC 算法或使用 RSA/ECDSA 的公用/專用密鑰對 JWT 進行簽名。
使用 JWT 主要用來下面兩點
認(rèn)證(Authorization)
:這是使用 JWT 最常見的一種情況捏鱼,一旦用戶登錄,后面每個請求都會包含 JWT酪耕,從而允許用戶訪問該令牌所允許的路由导梆、服務(wù)和資源。單點登錄
是當(dāng)今廣泛使用 JWT 的一項功能迂烁,因為它的開銷很小看尼。信息交換(Information Exchange)
:JWT 是能夠安全傳輸信息的一種方式。通過使用公鑰/私鑰對 JWT 進行簽名認(rèn)證盟步。此外藏斩,由于簽名是使用head
和payload
計算的,因此你還可以驗證內(nèi)容是否遭到篡改却盘。
JWT 的格式
下面狰域,我們會探討一下 JWT 的組成和格式是什么
JWT 主要由三部分組成,每個部分用 .
進行分割黄橘,各個部分分別是
Header
Payload
Signature
因此兆览,一個非常簡單的 JWT 組成會是下面這樣
然后我們分別對不同的部分進行探討。
Header
Header 是 JWT 的標(biāo)頭塞关,它通常由兩部分組成:令牌的類型(即 JWT)
和使用的 簽名算法
抬探,例如 HMAC SHA256 或 RSA。
例如
{ "alg": "HS256", "typ": "JWT"}
指定類型和簽名算法后帆赢,Json 塊被 Base64Url
編碼形成 JWT 的第一部分小压。
Payload
Token 的第二部分是 Payload
,Payload 中包含一個聲明椰于。聲明是有關(guān)實體(通常是用戶)和其他數(shù)據(jù)的聲明怠益。共有三種類型的聲明:registered, public 和 private 聲明。
-
registered 聲明
:包含一組建議使用的預(yù)定義聲明廉羔,主要包括
public 聲明
:公共的聲明溉痢,可以添加任何的信息僻造,一般添加用戶的相關(guān)信息或其他業(yè)務(wù)需要的必要信息,但不建議添加敏感信息孩饼,因為該部分在客戶端可解密髓削。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 的發(fā)送者的真實身份
拼湊在一起
現(xiàn)在我們把上面的三個由點分隔的 Base64-URL 字符串部分組成在一起轩娶,這個字符串可以在 HTML 和 HTTP 環(huán)境中輕松傳遞這些字符串儿奶。
下面是一個完整的 JWT 示例,它對 header 和 payload 進行編碼鳄抒,然后使用 signature 進行簽名
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
JWT 和 Session Cookies 的不同
JWT 和 Session Cookies 都提供安全的用戶身份驗證闯捎,但是它們有以下幾點不同
密碼簽名
JWT 具有加密簽名,而 Session Cookies 則沒有许溅。
JSON 是無狀態(tài)的
JWT 是無狀態(tài)
的瓤鼻,因為聲明被存儲在客戶端
,而不是服務(wù)端內(nèi)存中贤重。
身份驗證可以在本地
進行茬祷,而不是在請求必須通過服務(wù)器數(shù)據(jù)庫或類似位置中進行。這意味著可以對用戶進行多次身份驗證并蝗,而無需與站點或應(yīng)用程序的數(shù)據(jù)庫進行通信祭犯,也無需在此過程中消耗大量資源。
可擴展性
Session Cookies 是存儲在服務(wù)器內(nèi)存中滚停,這就意味著如果網(wǎng)站或者應(yīng)用很大的情況下會耗費大量的資源盹憎。由于 JWT 是無狀態(tài)的,在許多情況下铐刘,它們可以節(jié)省服務(wù)器資源陪每。因此 JWT 要比 Session Cookies 具有更強的可擴展性
。
JWT 支持跨域認(rèn)證
Session Cookies 只能用在單個節(jié)點的域
或者它的子域
中有效镰吵。如果它們嘗試通過第三個節(jié)點訪問檩禾,就會被禁止。如果你希望自己的網(wǎng)站和其他站點建立安全連接時疤祭,這是一個問題盼产。
使用 JWT 可以解決這個問題,使用 JWT 能夠通過多個節(jié)點
進行用戶認(rèn)證勺馆,也就是我們常說的跨域認(rèn)證
戏售。
JWT 和 Session Cookies 的選型
我們上面探討了 JWT 和 Cookies 的不同點侨核,相信你也會對選型有了更深的認(rèn)識,大致來說
對于只需要登錄用戶并訪問存儲在站點數(shù)據(jù)庫中的一些信息的中小型網(wǎng)站來說灌灾,Session Cookies 通常就能滿足搓译。
如果你有企業(yè)級站點,應(yīng)用程序或附近的站點锋喜,并且需要處理大量的請求些己,尤其是第三方或很多第三方(包括位于不同域的API),則 JWT 顯然更適合嘿般。