前言
本文將首先概述基于cookie的身份驗(yàn)證方式和基于token的身份驗(yàn)證方式罪郊,在此基礎(chǔ)上對兩種驗(yàn)證進(jìn)行比較蠕蚜。
最后將介紹JWT(主要是翻譯官網(wǎng)介紹)。
概述
HTTP是一個“無狀態(tài)”協(xié)議悔橄,這意味著Web應(yīng)用程序服務(wù)器在響應(yīng)客戶端請求時不會將多個請求鏈接到任何一個客戶端靶累。然而,許多Web應(yīng)用程序的安全和正常運(yùn)行都取決于系統(tǒng)能夠區(qū)分用戶并識別用戶及其權(quán)限癣疟。
這就需要一些機(jī)制來為一個HTTP請求提供狀態(tài)挣柬。它們使站點(diǎn)能夠在會話期間對各用戶做出適當(dāng)?shù)捻憫?yīng),從而保持跟蹤用戶在應(yīng)用程序中的活動(請求和響應(yīng))睛挚。
cookie和token
下面兩圖大致展示了基于cookie和基于token工作流程邪蛔。
基于cookie的身份驗(yàn)證
cookie是源自站點(diǎn)并由瀏覽器存儲在客戶計算機(jī)上的簡單文件。它們通常包含一個名稱和一個值扎狱,用于將客戶端標(biāo)識為對站點(diǎn)具有特定許可權(quán)的特定用戶侧到。
cookie與源域相連接的方式可以確保僅源域能夠訪問其中存儲的信息。第三方服務(wù)器既不能讀取也不能更改用戶計算機(jī)上該域的cookie內(nèi)容淤击。
網(wǎng)景公司的前雇員于1993年發(fā)明了cookie匠抗。
基于cookie的驗(yàn)證是有狀態(tài)的,就是說驗(yàn)證或者會話信息必須同時在客戶端和服務(wù)端保存污抬。這個信息服務(wù)端一般在數(shù)據(jù)庫中記錄汞贸,而前端會保存在cookie中。
驗(yàn)證的一般流程如下:
- 用戶輸入登陸憑據(jù)印机;
- 服務(wù)器驗(yàn)證憑據(jù)是否正確矢腻,并創(chuàng)建會話,然后把會話數(shù)據(jù)存儲在數(shù)據(jù)庫中射赛;
- 具有會話id的cookie被放置在用戶瀏覽器中多柑;
- 在后續(xù)請求中,服務(wù)器會根據(jù)數(shù)據(jù)庫驗(yàn)證會話id楣责,如果驗(yàn)證通過顷蟆,則繼續(xù)處理;
- 一旦用戶登出腐魂,服務(wù)端和客戶端同時銷毀該會話帐偎。
基于token的身份驗(yàn)證
隨著單頁面應(yīng)用程序的流行,以及Web API和物聯(lián)網(wǎng)的興起蛔屹,基于token的身份機(jī)制越來越被大家廣泛采用削樊。
當(dāng)討論基于token的身份驗(yàn)證時,一般都是說的JSON Web Tokens(JWT)。雖然有著很多不同的方式實(shí)現(xiàn)token漫贞,但是JWT已經(jīng)成為了事實(shí)上的標(biāo)準(zhǔn)甸箱,所以后面會將JWT和token混用。
基于token的驗(yàn)證是無狀態(tài)的迅脐。服務(wù)器不記錄哪些用戶已登陸或者已經(jīng)發(fā)布了哪些JWT芍殖。對服務(wù)器的每個請求都需要帶上驗(yàn)證請求的token。該標(biāo)記既可以加在header中谴蔑,可以在POST請求的主體中發(fā)送豌骏,也可以作為查詢參數(shù)發(fā)送。
工作流程如下:
- 用戶輸入登陸憑據(jù)隐锭;
- 服務(wù)器驗(yàn)證憑據(jù)是否正確窃躲,然后返回一個經(jīng)過簽名的token;
- 客戶端負(fù)責(zé)存儲token钦睡,可以存在local storage蒂窒,或者cookie中;
- 對服務(wù)器的請求帶上這個token荞怒;
- 服務(wù)器對JWT進(jìn)行解碼洒琢,如果token有效,則處理該請求褐桌;
- 一旦用戶登出纬凤,客戶端銷毀token。
token相對cookie的優(yōu)勢
無狀態(tài)
基于token的驗(yàn)證是無狀態(tài)的撩嚼,這也許是它相對cookie來說最大的優(yōu)點(diǎn)。后端服務(wù)不需要記錄token挖帘。每個令牌都是獨(dú)立的完丽,包括檢查其有效性所需的所有數(shù)據(jù),并通過聲明傳達(dá)用戶信息拇舀。
服務(wù)器唯一的工作就是在成功的登陸請求上簽署token逻族,并驗(yàn)證傳入的token是否有效。
防跨站請求偽造(CSRF)
舉個CSRF攻擊的例子骄崩,在網(wǎng)頁中有這樣的一個鏈接
![](http://bank.com?withdraw=1000&to=tom)
聘鳞,假設(shè)你已經(jīng)通過銀行的驗(yàn)證并且cookie中存在驗(yàn)證信息,同時銀行網(wǎng)站沒有CSRF保護(hù)要拂。一旦用戶點(diǎn)了這個圖片抠璃,就很有可能從銀行向tom這個人轉(zhuǎn)1000塊錢。
但是如果銀行網(wǎng)站使用了token作為驗(yàn)證手段脱惰,攻擊者將無法通過上面的鏈接轉(zhuǎn)走你的錢搏嗡。(因?yàn)楣粽邿o法獲取正確的token)
多站點(diǎn)使用
cookie綁定到單個域。foo.com域產(chǎn)生的cookie無法被bar.com域讀取。使用token就沒有這樣的問題采盒。這對于需要向多個服務(wù)獲取授權(quán)的單頁面應(yīng)用程序尤其有用旧乞。
使用token,使得用從myapp.com獲取的授權(quán)向myservice1.com和myservice2.com獲取服務(wù)成為可能磅氨。
支持移動平臺
好的API可以同時支持瀏覽器尺栖,iOS和Android等移動平臺。然而烦租,在移動平臺上延赌,cookie是不被支持的。
性能
一次網(wǎng)絡(luò)往返時間(通過數(shù)據(jù)庫查詢session信息)總比做一次HMACSHA256計算的Token驗(yàn)證和解析要費(fèi)時得多左权。
JWT
JWT是JSON Web Token的縮寫皮胡。它定義了一種緊湊且獨(dú)立的方式,用于將各方之間的信息安全地傳輸為JSON對象赏迟。這是一個開放的標(biāo)準(zhǔn)屡贺,見RFC 7519。
基于JWT的信息可以通過數(shù)字簽名進(jìn)行校驗(yàn)锌杀。校驗(yàn)的方法即可以使用消息摘要(HMAC)甩栈,或者非對稱加密(RSA)。
JWT具有兩個特點(diǎn):
- 緊湊糕再。由于其較小的尺寸量没,JWT可以通過URL,POST參數(shù)或者HTTP頭發(fā)送突想。較小的尺寸會帶來傳輸速度的優(yōu)勢殴蹄;
- 自包含:token中包含了用戶的所有必須信息,避免了多次查詢數(shù)據(jù)庫的需要猾担。
應(yīng)用場景
以下是JWT有用的一些場景
- 驗(yàn)證:這是JWT最常用的場景袭灯。一旦用戶登陸成功,每個后續(xù)的請求將包括JWT绑嘹,服務(wù)器在對JWT進(jìn)行驗(yàn)證后稽荧,允許用戶訪問服務(wù)和資源。單點(diǎn)登陸是一個廣泛使用JWT的場景工腋,因?yàn)樗拈_銷相對較小姨丈,并且能夠在不同的域中輕松使用。
- 信息交換:JWT是在可以安全地傳輸信息擅腰。因?yàn)镴WT可以被簽名蟋恬,收信人可以確認(rèn)發(fā)信人的身份,同時也能夠驗(yàn)證內(nèi)容是否被篡改趁冈。
格式
JWT包括三個部分:頭部筋现、載荷和簽名,這三個部分通過.
連接起來。
因此矾飞,一個典型的JWT長這樣xxxxx.yyyyy.zzzzz
一膨。
頭部
頭部通常包括兩部分:token類型(JWT),和使用到的算法洒沦,如HMAC豹绪、SHA256或RSA,下面是一個例子申眼,說明這是一個JWT瞒津,使用的簽名算法是HS256。
{
"alg": "HS256",
"typ": "JWT"
}
頭部會通過Base64Url編碼形成JWT的第一部分
載荷
第二部分是載荷括尸,要傳遞出去的聲明巷蚪,其中包含了實(shí)體(通常是用戶)和附加元數(shù)據(jù)。有三種類型的聲明:
- 保留聲明:這是一組預(yù)定義的聲明濒翻,非強(qiáng)制性屁柏,用來幫助接收方(服務(wù)器)更好地理解這個JWT。其中包括:iss(issuer有送,該JWT的簽發(fā)者)淌喻,exp(expiration time,過期時間)雀摘,sub(subject裸删,該JWT所面向的用戶),aud(audience阵赠,JWT的接收者)涯塔,和另外一些聲明
- 公共聲明:這些可以用使用JWT的人隨意定義。但是為了避免沖突清蚀,應(yīng)在在IANA JSON WEB令牌注冊表中定義它們匕荸,或者將其定義為包含防沖突命名空間的URI。
- 私有聲明:這些是為了在同意使用它們的各方之間共享信息而創(chuàng)建的自定義聲明轧铁。
下面是一個例子
{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}
載荷會通過Base64Url編碼形成JWT的第二部分
簽名
將上面兩部分編碼后,使用.
連接在一起旦棉,形成了xxxxx.yyyyyy齿风。
最后,采用頭部指定的算法绑洛,和私鑰對上面的字符串進(jìn)行簽名救斑。
加入采用的是HMAC SHA256 算法,簽名將通過下面的方式生成
HMACSHA256(base64UrlEncode(header) + "." +base64UrlEncode(payload),secret)
該簽名用戶驗(yàn)證JWT發(fā)送者的身份真屯,并確保該消息沒有被篡改脸候。
JWT工作流程
在身份驗(yàn)證過程中,一旦用戶使用其憑據(jù)成功登陸,服務(wù)器將返回JWT运沦,該JWT必須在客戶端本地保存泵额。這和服務(wù)器創(chuàng)建會話并返回cookie的傳統(tǒng)方法不同。
每次用戶要請求受保護(hù)的資源時携添,必須在請求中帶上JWT嫁盲。通常在Authorization頭Bearer中,如下:
Authorization: Bearer <token>
這是一種無狀態(tài)的認(rèn)證機(jī)制烈掠,因?yàn)橛脩魻顟B(tài)永遠(yuǎn)不會保存在服務(wù)器內(nèi)存中羞秤。服務(wù)器的受保護(hù)路由將在授權(quán)頭中檢查有效的JWT,如果存在左敌,則允許用戶訪問受保護(hù)的資源羽戒。由于JWT是自說明的梁棠,包含了所有必要的信息,這就減少了多次查詢數(shù)據(jù)庫的需要。
這樣可以完全依賴無狀態(tài)的數(shù)據(jù)API届巩,甚至可以向下游服務(wù)發(fā)出請求。API的作用域并不重要礼烈,因此跨源資源共享(CORS)不會是一個問題峭拘,因?yàn)樗皇褂肅ookie。
整個流程如下圖:
使用JWT的理由
現(xiàn)在來談?wù)凧WT與簡單網(wǎng)頁令牌(SWT)和安全斷言標(biāo)記語言令牌(SAML)相比的優(yōu)勢咬扇。
由于JSON比XML更短小甲葬,編碼時其大小也較小,使得JWT比SAML更緊湊懈贺。這使得JWT成為在HTML和HTTP環(huán)境中能更快地傳遞经窖。
從安全角度來說,SWT只能通過使用HMAC算法的共享密鑰進(jìn)行對稱簽名梭灿。但是画侣,JWT和SAML令牌可以以X.509證書的形式使用公鑰/私鑰對進(jìn)行簽名。與簡單的JSON簽名相比堡妒,使用XML數(shù)字簽名簽名XML而不引入模糊的安全漏洞是非常困難的配乱。
JSON解析器在大多數(shù)編程語言中很常見,因?yàn)樗鼈冎苯佑成涞綄ο笃こ佟O喾窗崮啵琗ML沒有自然的文檔對對象映射。這使得使用JWT比SAML斷言更容易伏尼。
從使用平臺來說忿檩,JWT在Internet規(guī)模上使用。這突出了客戶端處理多個平臺上特別是移動平臺上的JSON Web令牌的便利性爆阶。