1. JSON Web Token是什么
JSON Web Token (JWT)是一個開放標(biāo)準(zhǔn)(RFC 7519),它定義了一種緊湊的溜畅、自包含的方式,用于作為JSON對象在各方之間安全地傳輸信息肴熏。該信息可以被驗(yàn)證和信任忽孽,因?yàn)樗菙?shù)字簽名的。
2. 什么時候你應(yīng)該用JSON Web Tokens
下列場景中使用JSON Web Token是很有用的:
Authorization?(授權(quán)) : 這是使用JWT的最常見場景盯另。一旦用戶登錄性含,后續(xù)每個請求都將包含JWT,允許用戶訪問該令牌允許的路由鸳惯、服務(wù)和資源商蕴。單點(diǎn)登錄是現(xiàn)在廣泛使用的JWT的一個特性,因?yàn)樗拈_銷很小芝发,并且可以輕松地跨域使用绪商。
Information Exchange?(信息交換) : 對于安全的在各方之間傳輸信息而言,JSON Web Tokens無疑是一種很好的方式辅鲸。因?yàn)镴WTs可以被簽名格郁,例如,用公鑰/私鑰對独悴,你可以確定發(fā)送人就是它們所說的那個人例书。另外,由于簽名是使用頭和有效負(fù)載計(jì)算的刻炒,您還可以驗(yàn)證內(nèi)容沒有被篡改决采。
3. JSON Web Token的結(jié)構(gòu)是什么樣的
JSON Web Token由三部分組成,它們之間用圓點(diǎn)(.)連接坟奥。這三部分分別是:
Header
Payload
Signature
因此织狐,一個典型的JWT看起來是這個樣子的:
xxxxx.yyyyy.zzzzz
接下來,具體看一下每一部分:
Header
header典型的由兩部分組成:token的類型(“JWT”)和算法名稱(比如:HMAC SHA256或者RSA等等)筏勒。
例如:
然后移迫,用Base64對這個JSON編碼就得到JWT的第一部分
Payload
JWT的第二部分是payload,它包含聲明(要求)管行。聲明是關(guān)于實(shí)體(通常是用戶)和其他數(shù)據(jù)的聲明厨埋。聲明有三種類型: registered, public 和 private。
Registered claims : 這里有一組預(yù)定義的聲明捐顷,它們不是強(qiáng)制的荡陷,但是推薦雨效。比如:iss (issuer), exp (expiration time), sub (subject), aud (audience)等。
Public claims : 可以隨意定義废赞。
Private claims : 用于在同意使用它們的各方之間共享信息徽龟,并且不是注冊的或公開的聲明。
下面是一個例子:
對payload進(jìn)行Base64編碼就得到JWT的第二部分
注意唉地,不要在JWT的payload或header中放置敏感信息据悔,除非它們是加密的。
Signature
為了得到簽名部分耘沼,你必須有編碼過的header极颓、編碼過的payload、一個秘鑰群嗤,簽名算法是header中指定的那個菠隆,然對它們簽名即可。
例如:
HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)
簽名是用于驗(yàn)證消息在傳遞過程中有沒有被更改狂秘,并且骇径,對于使用私鑰簽名的token,它還可以驗(yàn)證JWT的發(fā)送方是否為它所稱的發(fā)送方者春。
看一張官網(wǎng)的圖就明白了:
4. JSON Web Tokens是如何工作的
在認(rèn)證的時候既峡,當(dāng)用戶用他們的憑證成功登錄以后,一個JSON Web Token將會被返回碧查。此后,token就是用戶憑證了校仑,你必須非常小心以防止出現(xiàn)安全問題忠售。一般而言,你保存令牌的時候不應(yīng)該超過你所需要它的時間迄沫。
無論何時用戶想要訪問受保護(hù)的路由或者資源的時候稻扬,用戶代理(通常是瀏覽器)都應(yīng)該帶上JWT,典型的羊瘩,通常放在Authorization header中泰佳,用Bearer schema。
header應(yīng)該看起來是這樣的:
Authorization: Bearer <token>
服務(wù)器上的受保護(hù)的路由將會檢查Authorization header中的JWT是否有效尘吗,如果有效逝她,則用戶可以訪問受保護(hù)的資源。如果JWT包含足夠多的必需的數(shù)據(jù)睬捶,那么就可以減少對某些操作的數(shù)據(jù)庫查詢的需要黔宛,盡管可能并不總是如此。
如果token是在授權(quán)頭(Authorization header)中發(fā)送的擒贸,那么跨源資源共享(CORS)將不會成為問題臀晃,因?yàn)樗皇褂胏ookie觉渴。
下面這張圖顯示了如何獲取JWT以及使用它來訪問APIs或者資源:
應(yīng)用(或者客戶端)想授權(quán)服務(wù)器請求授權(quán)。例如徽惋,如果用授權(quán)碼流程的話案淋,就是/oauth/authorize
當(dāng)授權(quán)被許可以后,授權(quán)服務(wù)器返回一個access token給應(yīng)用
應(yīng)用使用access token訪問受保護(hù)的資源(比如:API)
5.?基于Token的身份認(rèn)證 與 基于服務(wù)器的身份認(rèn)證
5.1.?基于服務(wù)器的身份認(rèn)證
在討論基于Token的身份認(rèn)證是如何工作的以及它的好處之前险绘,我們先來看一下以前我們是怎么做的:
HTTP協(xié)議是無狀態(tài)的踢京,也就是說,如果我們已經(jīng)認(rèn)證了一個用戶隆圆,那么他下一次請求的時候漱挚,服務(wù)器不知道我是誰,我們必須再次認(rèn)證
傳統(tǒng)的做法是將已經(jīng)認(rèn)證過的用戶信息存儲在服務(wù)器上渺氧,比如Session旨涝。用戶下次請求的時候帶著Session ID,然后服務(wù)器以此檢查用戶是否認(rèn)證過侣背。
這種基于服務(wù)器的身份認(rèn)證方式存在一些問題:
Sessions : 每次用戶認(rèn)證通過以后白华,服務(wù)器需要創(chuàng)建一條記錄保存用戶信息,通常是在內(nèi)存中贩耐,隨著認(rèn)證通過的用戶越來越多弧腥,服務(wù)器的在這里的開銷就會越來越大。
Scalability : 由于Session是在內(nèi)存中的潮太,這就帶來一些擴(kuò)展性的問題管搪。
CORS : 當(dāng)我們想要擴(kuò)展我們的應(yīng)用,讓我們的數(shù)據(jù)被多個移動設(shè)備使用時铡买,我們必須考慮跨資源共享問題更鲁。當(dāng)使用AJAX調(diào)用從另一個域名下獲取資源時,我們可能會遇到禁止請求的問題奇钞。
CSRF :?用戶很容易受到CSRF攻擊澡为。
5.2.?JWT與Session的差異
相同點(diǎn)是,它們都是存儲用戶信息景埃;然而媒至,Session是在服務(wù)器端的,而JWT是在客戶端的谷徙。
Session方式存儲用戶信息的最大問題在于要占用大量服務(wù)器內(nèi)存拒啰,增加服務(wù)器的開銷。
而JWT方式將用戶狀態(tài)分散到了客戶端中完慧,可以明顯減輕服務(wù)端的內(nèi)存壓力图呢。
Session的狀態(tài)是存儲在服務(wù)器端,客戶端只有session id;而Token的狀態(tài)是存儲在客戶端蛤织。
5.3. 基于Token的身份認(rèn)證是如何工作的
基于Token的身份認(rèn)證是無狀態(tài)的赴叹,服務(wù)器或者Session中不會存儲任何用戶信息。
沒有會話信息意味著應(yīng)用程序可以根據(jù)需要擴(kuò)展和添加更多的機(jī)器指蚜,而不必?fù)?dān)心用戶登錄的位置乞巧。
雖然這一實(shí)現(xiàn)可能會有所不同,但其主要流程如下:
用戶攜帶用戶名和密碼請求訪問
服務(wù)器校驗(yàn)用戶憑據(jù)
應(yīng)用提供一個token給客戶端
客戶端存儲token摊鸡,并且在隨后的每一次請求中都帶著它
服務(wù)器校驗(yàn)token并返回?cái)?shù)據(jù)
注意:
每一次請求都需要token
Token應(yīng)該放在請求header中
我們還需要將服務(wù)器設(shè)置為接受來自所有域的請求绽媒,用Access-Control-Allow-Origin: *
5.4. 用Token的好處
無狀態(tài)和可擴(kuò)展性:Tokens存儲在客戶端。完全無狀態(tài)免猾,可擴(kuò)展是辕。我們的負(fù)載均衡器可以將用戶傳遞到任意服務(wù)器,因?yàn)樵谌魏蔚胤蕉紱]有狀態(tài)或會話信息猎提。
安全:Token不是Cookie获三。(The token, not a cookie.)每次請求的時候Token都會被發(fā)送。而且锨苏,由于沒有Cookie被發(fā)送疙教,還有助于防止CSRF攻擊。即使在你的實(shí)現(xiàn)中將token存儲到客戶端的Cookie中伞租,這個Cookie也只是一種存儲機(jī)制贞谓,而非身份認(rèn)證機(jī)制。沒有基于會話的信息可以操作葵诈,因?yàn)槲覀儧]有會話!
還有一點(diǎn)裸弦,token在一段時間以后會過期,這個時候用戶需要重新登錄作喘。這有助于我們保持安全理疙。還有一個概念叫token撤銷,它允許我們根據(jù)相同的授權(quán)許可使特定的token甚至一組token無效徊都。
5.5. JWT與OAuth的區(qū)別
OAuth2是一種授權(quán)框架 广辰,JWT是一種認(rèn)證協(xié)議
無論使用哪種方式切記用HTTPS來保證數(shù)據(jù)的安全性
OAuth2用在使用第三方賬號登錄的情況(比如使用weibo, qq, github登錄某個app),而JWT是用在前后端分離, 需要簡單的對后臺API進(jìn)行保護(hù)時使用择吊。
5.6. 關(guān)于OAuth可以參考下面幾篇