1.JWT即JSON Web Tokens,他可以用來安全的傳遞信息,因為這些信息是經過數字簽名的
2.JWT可以使用一種加密算法比如HMAC 算法,也可以使用公鑰/私鑰的非對稱算法
3.因為JWT簽名后的信息夠短,可以放在url里、request body里、http header里,傳輸夠快。
4.荷載信息里包含所有你想要的,避免不止一次的去查詢數據庫
5.JWT的使用場景主要包括:
1) 認證,這是比較常見的使用場景,只要用戶登錄過一次系統,之后的請求都會包含簽名出來的token,通過token也可以用來實現單點登錄。
2)交換信息,通過使用密鑰對來安全的傳送信息,可以知道發送者是誰、放置消息被篡改。
6.JSON Web Tokens由三部分組成,用英文句點分割(.) ,一般看起來例如:xxxxx.yyyyy.zzzzz
分為:
- Header 頭信息
- Payload 荷載信息,實際數據
- Signature 由頭信息+荷載信息+密鑰 組合之后進行加密得到
1) Header 頭信息通常包含兩部分,type:代表token的類型,這里使用的是JWT類型。 alg:使用的Hash算法,例如HMAC SHA256或RSA.
{ "alg": "HS256", "typ": "JWT" }
// 這會被經過base64Url編碼形成第一部分
2)Payload 一個token的第二個部分是荷載信息,它包含一些聲明Claim(實體的描述,通常是一個User信息,還包括一些其他的元數據)
聲明分三類:
1)Reserved Claims,這是一套預定義的聲明,並不是必須的,這是一套易於使用、操作性強的聲明。包括:iss(issuer)、exp(expiration time)、sub(subject)、aud(audience)等
2)Plubic Claims,
3)Private Claims,交換信息的雙方自定義的聲明
{ "sub": "1234567890", "name": "John Doe", "admin": true }
// 同樣經過Base64Url編碼后形成第二部分
3) signature 使用header中指定的算法將編碼后的header、編碼后的payload、一個secret進行加密
例如使用的是HMAC SHA256算法,大致流程類似於: HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)
這個signature字段被用來確認JWT信息的發送者是誰,並保證信息沒有被修改
7.這個JSON Web Tokens包含了必要的用戶信息,減少了對數據庫進行多次查詢的需要。
8.由於沒有使用Cookies,Cross-Origin Resource Sharing (CORS) ,跨域的資源訪問不會成為問題。
JWT官網有一張圖描述了JWT的認證過程:
9.JWT、JWS、JWE的區別(轉自https://securedb.co/community/jwt-vs-jws-vs-jwe/)
1)JWT(JSON Web Tokens),jwt長度較小,且可以使用URL傳輸(URL safe)。不想cookies只能在web環境起作用。 JWT可以同時使用在web環境和RESTfull的接口。
2)對於開發者來說,JWT與另外兩種相近的標准:JWS(JSON Web Signature)、JWE(JSON Web Encryption),容易引起混亂。
3)關於JWT的描述,可以參考RFC7519(https://tools.ietf.org/html/rfc7519)的描述:
JSON Web Token (JWT) 是一個間接地、URL安全的,表現為一組聲明,可以在雙方之間進行傳輸。一個JWT的聲明,是指經過編碼后的一個JSON對象,這個JSON對象可以是一個JSON Web Signature(JWS)結構的荷載(payload),或者是一個JSON Web Encryption(JWE)結構的明文。允許使用聲明進行數字簽名,或者通過一個Message Authentication Code(MAC)進行完整性保護可選擇是否加密。
簡單來說,JWTs表現為一組被編碼為JWS and/or JWE結構的JSON object的聲明(Claim).
換言之,一組JWT聲明(就是表現為JSON格式的Claims)被通過JWS結構或者JWE結構(或者同時使用兩種)發送,決定於你如何去實現它。所以,當你發送JWT給別人是,它實際上是一個JWT荷載或者JWE荷載。JWS荷載更加常用。
關於聲明(Claim),他們是關於用戶的簡單斷言(assertion)。比如,對於一個用戶在工資系統中進行認證,這組Claims可能看起來像這樣:
{ "userId":"johndoe", "role":"employee", "pay-frequency":"biweekly" }
現在,將它嵌入一個JWS結構,整個字符串看起來像是這樣:
{ "alg":"HS256" } // End of JOSE Header . { "userId": "johndoe", "role": "employee", "pay-frequency": "biweekly" } // End of JWT Claims . { } // End of Signature in case of JWS
4)關於JWS
顧名思義,JWS模式對這個內容進行了數字化簽名。這個內容被用來存放JWT的聲明.服務端簽名出JWT並且發送到客戶端,並在用戶成功認證后進行應答。服務器期望客戶端在下次請求的時候將JWS作為請求的一部分,發送回服務端。
如果我們處理的客戶端是欺騙者則么辦?這就是簽名(signature)需要出場的地方了。簽名攜帶了完整的可驗證的信息。換句話說,服務器可以確認,接收到的JWT聲明里的JWS是沒有經過欺騙客戶端、中間者進行修改的。
服務端通過驗證消息的簽名來確保客戶端沒有修改聲明。如果服務端檢測到任何修改,可以采取適當的動作(拒絕這次請求或者鎖定客戶端之類的)
客戶端同樣可以驗證簽名,為了做到這點,客戶端也需要服務端的secret(密鑰)(如果這個JWT簽名是HMAC算法),或者需要服務端對公鑰(如果這個WJT是數字化簽名)
特別注意:對於JWS,荷載(聲明部分)沒有進行加密,所以,不要發送任何敏感信息.
5)關於JWE
JWE模式會對內容加密,而不是簽名。JWT的聲明會被加密。因此JWE帶來了保密性。JWE可以被簽名並附在JWS里。這樣的話就可以同時加密和簽名。因此得到了保密性(Confidentiality)、完整性(Integrity)、可認證(Authentication)。
6)那么對於客戶端,如何分辨JWS或者JWE呢?
JWS的Header與JWE的Header是不同的,可以通過檢查“alg”Header參數的值來區分。如果這個值表現為一個數字簽名或者MAC的算法,或者是”none“,則它是一個JWS。
如果它表現為一個 Key Encryption, Key Wrapping, Direct Key Agreement, Key Agreement with Key Wrapping, or Direct Encryption algorithm。則它是一個JWE。
還可以通過Header里的“enc”(encryption algorithm)是否存在來判斷,如果"enc"這個成員存在的話說明是JWE,否則的話就是JWS.