JWT是啥?
JWT就是一個字符串,經過加密處理與校驗處理的字符串,形式為:
A.B.C
A由JWT頭部信息header加密得到
B由JWT用到的身份驗證信息json數據加密得到
C由A和B加密得到,是校驗部分
怎樣生成A?
header格式為:
{ "typ": "JWT", "alg": "HS256" }
它就是一個json串,兩個字段是必須的,不能多也不能少。alg
字段指定了生成C的算法,默認值是HS256
將header用base64加密,得到A
通常,JWT庫中,可以把A部分固定寫死,用戶最多指定一個alg
的取值
怎樣計算B?
根據JWT claim set[用base64]加密得到的。claim set是一個json數據,是表明用戶身份的數據,可自行指定字段很靈活,也有固定字段表示特定含義(但不一定要包含特定字段,只是推薦)。
這里偷懶,直接用php中的代碼來表示claim set了,重在說明字段含義:
$token = array( "iss" => "http://example.org", #非必須。issuer 請求實體,可以是發起請求的用戶的信息,也可是jwt的簽發者。 "iat" => 1356999524, #非必須。issued at。 token創建時間,unix時間戳格式 "exp" => "1548333419", #非必須。expire 指定token的生命周期。unix時間戳格式 "aud" => "http://example.com", #非必須。接收該JWT的一方。 "sub" => "jrocket@example.com", #非必須。該JWT所面向的用戶 "nbf" => 1357000000, # 非必須。not before。如果當前時間在nbf里的時間之前,則Token不被接受;一般都會留一些余地,比如幾分鍾。 "jti" => '222we', # 非必須。JWT ID。針對當前token的唯一標識 "GivenName" => "Jonny", # 自定義字段 "Surname" => "Rocket", # 自定義字段 "Email" => "jrocket@example.com", # 自定義字段 "Role" => ["Manager", "Project Administrator"] # 自定義字段 );
JWT遵循RFC7519,里面提到claim set的json數據中,自定義字段的key是一個string,value是一個json數據。因此隨意編寫吧,很靈活。
個人初學,認為一個最基本最簡單最常用的claim set為:
$token=array( "user_id" => 123456, #用戶id,表明用戶 "iat" => 1356999524, #token發布時間 "exp" => 1556999524, #token過期時間 );
將claim set加密后得到B
,學名payload
怎樣計算C?
將A.B
使用HS256加密(其實是用header中指定的算法),當然加密過程中還需要密鑰(自行指定的一個字符串)。
加密得到C
,學名signature
,其實就是一個字符串。作用類似於CRC校驗,保證加密沒有問題。
好了,現在A.B.C
就是生成的token了。
怎樣使用token?
可以放到HTTP請求的請求頭中,通常是Authorization
字段。
也有人說放到cookie。不過移動端app用cookie似乎不方便。
token應用流程?
- 初次登錄:用戶初次登錄,輸入用戶名密碼
- 密碼驗證:服務器從數據庫取出用戶名和密碼進行驗證
- 生成JWT:服務器端驗證通過,根據從數據庫返回的信息,以及預設規則,生成JWT
- 返還JWT:服務器的HTTP RESPONSE中將JWT返還
- 帶JWT的請求:以后客戶端發起請求,HTTP REQUEST HEADER中的Authorizatio字段都要有值,為JWT
服務器端在處理到達的request之前,會將request中的Token值與保存在當前用戶session中的令牌值進行比較,看是否匹配。
在處理完該request后,且在response發送給客戶端之前,將會產生一個新的 Token,該Token除傳給客戶端以外,也會將用戶session中保存的舊的Token進行替換。
這樣,如果用戶會退到剛才的提交頁面並再次提交的話,客戶端傳過來的Token值和服務器端的不一致,從而有效地防止了重復提交地發生。