支持跨域訪問,無狀態認證
token特點
支持跨域訪問:
Cookie是不允許垮域訪問的,這一點對Token機制是不存在的,前提是傳輸的用戶認證信息通過HTTP頭傳輸
無狀態(也稱:服務端可擴展行):
Token機制在服務端不需要存儲session信息,因為Token 自身包含了所有登錄用戶的信息,
只需要在客戶端的cookie或本地介質存儲狀態信息
更適用CDN:
可以通過內容分發網絡請求你服務端的所有資料(如:javascript,HTML,圖片等),而你的服務端只要提供API即可
去耦:
不需要綁定到一個特定的身份驗證方案。Token可以在任何地方生成,只要在你的API被調用的時候,你可以進行Token生成調用即可
更適用於移動應用:
當你的客戶端是一個原生平台(iOS, Android)時,Cookie是不被支持的(你需要通過Cookie容器進行處理),
這時采用Token認證機制就會簡單得多。
CSRF:
因為不再依賴於Cookie,所以你就不需要考慮對CSRF(跨站請求偽造)的防范。
token基本原理
Request
指在一次請求的全過程中有效,即從http請求到服務器處理結束,返回響應的整個過程,存放在HttpServletRequest
對象中。
Session
是用戶全局變量,在整個會話期間都有效。只要頁面不關閉就一直有效(或者直到用戶一直未活動導致會話過期,默認session過期時間為30分鍾)
token 認證過程
客戶端使用用戶名跟密碼請求登錄
服務端收到請求,去驗證用戶名與密碼
驗證成功后,服務端會簽發一個 Token,再把這個 Token 發送給客戶端
客戶端收到 Token 以后可以把它存儲起來,比如放在 Cookie 里或者 Local Storage 里
客戶端每次向服務端請求資源的時候需要帶着服務端簽發的 Token
服務端收到請求,然后去驗證客戶端請求里面帶着的 Token,如果驗證成功,就向客戶端返回請求的數據
因為token是被簽名的,所以我們可以認為一個可以解碼認證通過的token是由我們系統發放的,其中帶的信息是合法有效的
基於JWT的Token認證
JSON Web Token(JWT)
是一個非常輕巧的規范。這個規范允許我們使用JWT在用戶和服務器之間傳遞安全可靠的信息。
JWT的組成:
一個JWT實際上就是一個字符串,它由三部分組成,頭部
、載荷
與簽名
頭部(Header)
用於描述關於該JWT的最基本的信息,例如其類型以及簽名所用的算法等。這也可以被表示成一個JSON對象。
然后將其進行base64編碼,得到第一部分
{
"typ": "JWT",
"alg": "HS256"
}
載荷(Payload)
一般添加用戶的相關信息或其他業務需要的必要信息。但不建議添加敏感信息,因為該部分在客戶端可解密
(base64是對稱解密的,意味着該部分信息可以歸類為明文信息)
然后將其進行base64編碼,得到第二部分
{ "iss": "JWT Builder",
"iat": 1416797419,
"exp": 1448333419,
"aud": "www.example.com",
"sub": "aaa@example.com",
"Email": "aaa@example.com",
"Role": [ "admin", "user" ]
}
iss:
該JWT的簽發者,是否使用是可選的;
sub:
該JWT所面向的用戶,是否使用是可選的;
aud:
接收該JWT的一方,是否使用是可選的;
exp(expires):
什么時候過期,這里是一個Unix時間戳,是否使用是可選的;
iat(issued at):
在什么時候簽發的(UNIX時間),是否使用是可選的;
nbf (Not Before):
如果當前時間在nbf里的時間之前,則Token不被接受;是否使用是可選的;
jti:
JWT的唯一身份標識,主要用來作為一次性token,從而回避重放攻擊。
簽名(Signature)
需要base64加密后的header和base64加密后的payload使用"."連接組成的字符串,
然后通過header中聲明的加密方式進行加鹽secret組合加密(在加密的時候,我們還需要提供一個密鑰(secret),加鹽secret組合加密)
然后就構成了jwt的第三部分。
最后,將這一部分簽名也拼接在被簽名的字符串后面,我們就得到了完整的JWT
注意:secret就是你服務端的私鑰,在任何場景都不應該流露出去。
一旦客戶端得知這個secret, 那就意味着客戶端是可以自我簽發jwt了