JWT(Json Web Token)定義了一種使用Json形式在網(wǎng)絡(luò)間安全地傳遞信息的簡潔開放的標(biāo)準(zhǔn)(RFC 7519)。JWT使用數(shù)字簽名確保信息是可信的。
一婉商、Session認(rèn)證和Token認(rèn)證
Http協(xié)議本身是無狀態(tài)的晶通,如果用戶向服務(wù)器傳遞了用戶名和密碼進行了用戶認(rèn)證,那么下一次請求時用戶還是需要進行同樣的認(rèn)證华望,因為根據(jù)Http協(xié)議蕊蝗,我們無法知道請求是由哪個用戶發(fā)出的。所以赖舟,為了能識別哪個用戶蓬戚,免去每次都進行驗證的麻煩,就有了傳統(tǒng)的Session認(rèn)證和token認(rèn)證方案宾抓。
a) Session認(rèn)證
Session認(rèn)證的方案為:第一次用戶認(rèn)證請求通過時子漩,服務(wù)器端存儲用戶的登錄信息,然后在響應(yīng)時傳遞給瀏覽器石洗,瀏覽器保存為cookie幢泼,下次請求時把cookie發(fā)送給服務(wù)器,服務(wù)器根據(jù)cookie信息來識別是哪個用戶讲衫。
Session認(rèn)證適用于單個服務(wù)器的場合缕棵,如果用戶增多,需要部署多個服務(wù)器時涉兽,Session認(rèn)證就會暴露問題招驴。因為每個用戶在認(rèn)證后,服務(wù)器都會記錄Session枷畏,一般保存在內(nèi)存中忽匈,隨著認(rèn)證用戶增多,服務(wù)器開銷也會增大矿辽;而且認(rèn)證用戶的后續(xù)請求都需要到這臺保存了自己Session的服務(wù)器上驗證Cookie丹允。在多集群分布式的場合郭厌,這就造成了性能瓶頸,對負(fù)載均衡雕蔽、應(yīng)用的擴展都會造成影響折柠。
進程外Session通過將Session保存在數(shù)據(jù)庫或硬盤中可以解決服務(wù)器內(nèi)存開銷的問題,但仍然不便于擴展批狐。
b) Token認(rèn)證
Token認(rèn)證也是無狀態(tài)的扇售,不需要在服務(wù)端保存認(rèn)證用戶的信息,它的認(rèn)證流程為:用戶使用用戶名密碼請求服務(wù)器嚣艇;服務(wù)器驗證用戶承冰,如果驗證通過就發(fā)給用戶一個token;客戶端保存token食零,并在之后的每次請求都附上token困乒;服務(wù)端驗證token、返回數(shù)據(jù)贰谣。
Token認(rèn)證機制不需要保存認(rèn)證用戶的信息娜搂、也不需要考錄用戶在那臺服務(wù)器登錄,可以很好地適應(yīng)應(yīng)用的擴展吱抚。
token的體積很小百宇,請求服務(wù)端時,可以被附在URL秘豹、Header或是Post參數(shù)中携御。而且token中包含了用戶相關(guān)的必要、非私密的相信既绕,免去了服務(wù)端再次查詢數(shù)據(jù)庫的開銷啄刹。
c) JWT的使用場景
最常用于對已經(jīng)登錄用戶的認(rèn)證,比如單點登錄岸更,只需在每次請求中都附上JWT,JWT體積小巧且支持跨域膊升、多語言怎炊。
JWT也可以用于信息傳輸,因為有根據(jù)payload和header計算出的簽名的保護廓译,可以確保傳遞的信息不被篡改评肆。
三、JWT的構(gòu)成
JWT由Header非区、Payload瓜挽、Signature三部分構(gòu)成,之間用點號風(fēng)格征绸,構(gòu)成xx.yy.zz的形式久橙。
a) Header聲明了token類型俄占、算法類型(HMAC SHA256或RSA),比如
{
"alg": "HS256",
"typ": "JWT"
}
然后對header做Base64URL編碼淆衷。
b) Payload中保存了聲明信息缸榄,聲明信息有標(biāo)準(zhǔn)聲明、公開聲明祝拯、自定義聲明三種類型甚带,前兩種聲明在相關(guān)的標(biāo)準(zhǔn)中已經(jīng)規(guī)定https://www.iana.org/assignments/jwt/jwt.xhtml,推薦但不強制使用佳头,標(biāo)準(zhǔn)聲明舉例有:
iss: jwt簽發(fā)者
sub: jwt所面向的用戶
aud: 接收jwt的一方
exp: jwt的過期時間鹰贵,這個過期時間必須要大于簽發(fā)時間
nbf: 定義在什么時間之前,該jwt都是不可用的.
iat: jwt的簽發(fā)時間
jti: jwt的唯一身份標(biāo)識康嘉,主要用來作為一次性token,從而回避重放攻擊
發(fā)送方和接收方也可以自定聲明碉输。
{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}
載荷信息也使用Base64URL編碼。
c) Signature凄鼻,簽證信息是根據(jù)Header腊瑟、Payload的Base64URL編碼以及密鑰(Secret)加密生成的,加密算法使用header中定義的類型块蚌。
d) Secret信息只保存在服務(wù)端闰非,服務(wù)端為客戶端簽發(fā)jwt token要使用Secret,后續(xù)對客戶端遞交的jwt的驗證也要使用Secret峭范,所以一定要防止Secret的泄露财松。
四、JWT的使用
var secret = "h3h5k9kll789";
//JWT簽發(fā)
var payload = new Dictionary
{
{ "UserID",123},
{"UserName","admin" }
};
//指定HMAC加密算法
IJwtAlgorithm algorithm = new HMACSHA256Algorithm();
IJsonSerializer serializer = new JsonNetSerializer();
IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();
IJwtEncoder encoder = new JwtEncoder(algorithm, serializer, urlEncoder);
var token = encoder.Encode(payload, secret);
//JWT驗證及解析
IJsonSerializer serializer1 = new JsonNetSerializer();
IDateTimeProvider provider1 = new UtcDateTimeProvider();
IJwtValidator validator1 = new JwtValidator(serializer1, provider1);
IBase64UrlEncoder urlEncoder1 = new JwtBase64UrlEncoder();
IJwtDecoder decoder = new JwtDecoder(serializer1, validator1, urlEncoder1);
//解析出PayLoad
var json = decoder.Decode(token, secret, verify: true);
學(xué)習(xí)資料:如鵬網(wǎng).net提高班http://www.rupeng.com/News/10/4603.shtml
http://www.reibang.com/p/576dbf44b2ae
https://jwt.io/