1. JSON Web Token是什么
JSON Web Token (JWT)是一個開放標(biāo)準(RFC 7519),它定義了一種緊湊的、自包含的方式,用于作為JSON對象在各方之間安全地傳輸信息。該信息可以被驗證和信任,因為它是數(shù)字簽名的钉鸯。
2. 什么時候你應(yīng)該用JSON Web Tokens
下列場景中使用JSON Web Token是很有用的:
Authorization?(授權(quán)) : 這是使用JWT的最常見場景。一旦用戶登錄邮辽,后續(xù)每個請求都將包含JWT唠雕,允許用戶訪問該令牌允許的路由、服務(wù)和資源吨述。單點登錄是現(xiàn)在廣泛使用的JWT的一個特性岩睁,因為它的開銷很小,并且可以輕松地跨域使用揣云。
Information Exchange?(信息交換) : 對于安全的在各方之間傳輸信息而言捕儒,JSON Web Tokens無疑是一種很好的方式。因為JWTs可以被簽名邓夕,例如刘莹,用公鑰/私鑰對,你可以確定發(fā)送人就是它們所說的那個人焚刚。另外栋猖,由于簽名是使用頭和有效負載計算的,您還可以驗證內(nèi)容沒有被篡改汪榔。
3. JSON Web Token的結(jié)構(gòu)是什么樣的
JSON Web Token由三部分組成,它們之間用圓點(.)連接肃拜。這三部分分別是:
Header
Payload
Signature
因此痴腌,一個典型的JWT看起來是這個樣子的:
xxxxx.yyyyy.zzzzz
接下來,具體看一下每一部分:
Header
header典型的由兩部分組成:token的類型(“JWT”)和算法名稱(比如:HMAC SHA256或者RSA等等)燃领。
例如:
然后士聪,用Base64對這個JSON編碼就得到JWT的第一部分
Payload
JWT的第二部分是payload,它包含聲明(要求)猛蔽。聲明是關(guān)于實體(通常是用戶)和其他數(shù)據(jù)的聲明剥悟。聲明有三種類型: registered, public 和 private灵寺。
Registered claims : 這里有一組預(yù)定義的聲明,它們不是強制的区岗,但是推薦略板。比如:iss (issuer), exp (expiration time), sub (subject), aud (audience)等。
Public claims : 可以隨意定義慈缔。
Private claims : 用于在同意使用它們的各方之間共享信息叮称,并且不是注冊的或公開的聲明。
下面是一個例子:
對payload進行Base64編碼就得到JWT的第二部分
注意藐鹤,不要在JWT的payload或header中放置敏感信息瓤檐,除非它們是加密的。
Signature
為了得到簽名部分娱节,你必須有編碼過的header挠蛉、編碼過的payload、一個秘鑰肄满,簽名算法是header中指定的那個谴古,然對它們簽名即可。
例如:
HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)
簽名是用于驗證消息在傳遞過程中有沒有被更改悄窃,并且讥电,對于使用私鑰簽名的token,它還可以驗證JWT的發(fā)送方是否為它所稱的發(fā)送方轧抗。
看一張官網(wǎng)的圖就明白了:
4. JSON Web Tokens是如何工作的
在認證的時候恩敌,當(dāng)用戶用他們的憑證成功登錄以后,一個JSON Web Token將會被返回横媚。此后纠炮,token就是用戶憑證了,你必須非常小心以防止出現(xiàn)安全問題灯蝴。一般而言恢口,你保存令牌的時候不應(yīng)該超過你所需要它的時間。
無論何時用戶想要訪問受保護的路由或者資源的時候穷躁,用戶代理(通常是瀏覽器)都應(yīng)該帶上JWT耕肩,典型的,通常放在Authorization header中问潭,用Bearer schema猿诸。
header應(yīng)該看起來是這樣的:
Authorization: Bearer <token>
服務(wù)器上的受保護的路由將會檢查Authorization header中的JWT是否有效,如果有效狡忙,則用戶可以訪問受保護的資源梳虽。如果JWT包含足夠多的必需的數(shù)據(jù),那么就可以減少對某些操作的數(shù)據(jù)庫查詢的需要灾茁,盡管可能并不總是如此窜觉。
如果token是在授權(quán)頭(Authorization header)中發(fā)送的谷炸,那么跨源資源共享(CORS)將不會成為問題,因為它不使用cookie禀挫。
下面這張圖顯示了如何獲取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訪問受保護的資源(比如:API)
5.?基于Token的身份認證 與 基于服務(wù)器的身份認證
5.1.?基于服務(wù)器的身份認證
在討論基于Token的身份認證是如何工作的以及它的好處之前,我們先來看一下以前我們是怎么做的:
HTTP協(xié)議是無狀態(tài)的腻格,也就是說画拾,如果我們已經(jīng)認證了一個用戶,那么他下一次請求的時候菜职,服務(wù)器不知道我是誰青抛,我們必須再次認證
傳統(tǒng)的做法是將已經(jīng)認證過的用戶信息存儲在服務(wù)器上,比如Session酬核。用戶下次請求的時候帶著Session ID蜜另,然后服務(wù)器以此檢查用戶是否認證過。
這種基于服務(wù)器的身份認證方式存在一些問題:
Sessions : 每次用戶認證通過以后嫡意,服務(wù)器需要創(chuàng)建一條記錄保存用戶信息举瑰,通常是在內(nèi)存中,隨著認證通過的用戶越來越多蔬螟,服務(wù)器的在這里的開銷就會越來越大此迅。
Scalability : 由于Session是在內(nèi)存中的,這就帶來一些擴展性的問題旧巾。
CORS : 當(dāng)我們想要擴展我們的應(yīng)用耸序,讓我們的數(shù)據(jù)被多個移動設(shè)備使用時,我們必須考慮跨資源共享問題鲁猩。當(dāng)使用AJAX調(diào)用從另一個域名下獲取資源時坎怪,我們可能會遇到禁止請求的問題。
CSRF :?用戶很容易受到CSRF攻擊廓握。
5.2.?JWT與Session的差異
相同點是搅窿,它們都是存儲用戶信息;然而隙券,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的身份認證是如何工作的
基于Token的身份認證是無狀態(tài)的隔箍,服務(wù)器或者Session中不會存儲任何用戶信息。
沒有會話信息意味著應(yīng)用程序可以根據(jù)需要擴展和添加更多的機器脚乡,而不必擔(dān)心用戶登錄的位置蜒滩。
雖然這一實現(xiàn)可能會有所不同,但其主要流程如下:
用戶攜帶用戶名和密碼請求訪問
服務(wù)器校驗用戶憑據(jù)
應(yīng)用提供一個token給客戶端
客戶端存儲token奶稠,并且在隨后的每一次請求中都帶著它
服務(wù)器校驗token并返回數(shù)據(jù)
注意:
每一次請求都需要token
Token應(yīng)該放在請求header中
我們還需要將服務(wù)器設(shè)置為接受來自所有域的請求俯艰,用Access-Control-Allow-Origin: *
5.4. 用Token的好處
無狀態(tài)和可擴展性:Tokens存儲在客戶端。完全無狀態(tài)锌订,可擴展竹握。我們的負載均衡器可以將用戶傳遞到任意服務(wù)器,因為在任何地方都沒有狀態(tài)或會話信息辆飘。
安全:Token不是Cookie啦辐。(The token, not a cookie.)每次請求的時候Token都會被發(fā)送。而且蜈项,由于沒有Cookie被發(fā)送芹关,還有助于防止CSRF攻擊。即使在你的實現(xiàn)中將token存儲到客戶端的Cookie中紧卒,這個Cookie也只是一種存儲機制侥衬,而非身份認證機制。沒有基于會話的信息可以操作常侦,因為我們沒有會話!
還有一點浇冰,token在一段時間以后會過期,這個時候用戶需要重新登錄聋亡。這有助于我們保持安全肘习。還有一個概念叫token撤銷,它允許我們根據(jù)相同的授權(quán)許可使特定的token甚至一組token無效坡倔。
5.5. JWT與OAuth的區(qū)別
OAuth2是一種授權(quán)框架 漂佩,JWT是一種認證協(xié)議
無論使用哪種方式切記用HTTPS來保證數(shù)據(jù)的安全性
OAuth2用在使用第三方賬號登錄的情況(比如使用weibo, qq, github登錄某個app),而JWT是用在前后端分離, 需要簡單的對后臺API進行保護時使用罪塔。
5.6. 關(guān)于OAuth可以參考下面幾篇
6. 參考
https://tools.ietf.org/html/rfc7519#section-3
http://blog.leapoahead.com/2015/09/06/understanding-jwt/
https://cnodejs.org/topic/557844a8e3cc2f192486a8ff
http://blog.leapoahead.com/2015/09/07/user-authentication-with-jwt/