自從RESTful架構興起後,越來越多人提倡使用JWT來取代傳統Session
JAW 一般加入再在 web 的 Header 內, 常見 Authorization: Bearer JWTtoken
JWT是開放標準(RFC7519), 採用JSON格式. 並透過這編碼進行傳遞資訊. JWT會透過HMAC、RSA、ECDS等方式進行加密. 通常用JWT來對使用者進行驗證, 也就是使用者會先向伺服器取得JWT資料, 而後只要使用這JWT伺服器請求資源, 如果這JWT是有效, 那麼就能取得相關資源.
► JWT的組合
• Payload 結構
► 實作
JAW 一般加入再在 web 的 Header 內, 常見 Authorization: Bearer JWTtoken
JWT是開放標準(RFC7519), 採用JSON格式. 並透過這編碼進行傳遞資訊. JWT會透過HMAC、RSA、ECDS等方式進行加密. 通常用JWT來對使用者進行驗證, 也就是使用者會先向伺服器取得JWT資料, 而後只要使用這JWT伺服器請求資源, 如果這JWT是有效, 那麼就能取得相關資源.
► JWT的組合
• 由 urlBase64Encode(Header).urlBase64Encode(Payload).urlBase64Encode(Signature) JSON object經編碼及urlBase64然後用 . 來做區隔組成一個JWT字串
• Header : 定義加密方式
{<br /> "alg": "HS256", //加密方式<br /> "typ": "JWT"<br /> }
• Payload 結構
$payload = array( #非必須。issuer 請求實體,可以是發起請求的用戶的信息,也可是jwt的簽發者。 "iss" => $CFG->home, #非必須。 issued at。 token創建時間,unix時間戳格式 "iat" => $serverTime, #非必須。 expire 指定token的生命週期。 unix時間戳格式 "exp" => $serverTime + 60, #非必須。接收該JWT的一方。 "aud" => "http://vitv.org", #非必須。該JWT所面向的用戶 "sub" => "vitv@example.org", # 非必須。 not before。如果當前時間在nbf裡的時間之前,則Token不被接受;一般都會留一些餘地,比如幾分鐘。 "nbf" => 1234500000, # 非必須。 JWT ID。針對當前token的唯一標識 "jti" => '123ab', # 可自行定義字段 "Create" => "shioulo", );
• Signature : 簽章, 對 urlBase64Encode(Header).urlBase64Encode(Payload) 內容進行SHA256簽章以便事後確認資料的正確性
► 實作
function jwtEncode($payload, $key) { $jwtKey = $key; $jwt = urlBase64Encode(json_encode(['typ' => 'JWT', 'alg' => 'HS256'])) . '.' . urlBase64Encode(json_encode($payload)); return $jwt . '.' . signature($jwt, $jwtKey, 'SHA256'); } function signature($input, $key, $alg) { return urlBase64Encode(hash_hmac($alg, $input, $key, true)); } function jwtDecode($jwt, $decodKey, $serverTime) { $tokens = explode('.', $jwt); if (count($tokens) != 3) { return false; } list($header64, $payload64, $sign) = $tokens; $header = json_decode(urlBase64Decode($header64), JSON_OBJECT_AS_ARRAY); if (empty($header['alg'])) { return false; } if ( signature($header64 . '.' . $payload64, $decodKey, 'SHA256')!== $sign) { return false; } $payload = json_decode(urlBase64Decode($payload64), JSON_OBJECT_AS_ARRAY); if (isset($payload['iat']) && $payload['iat'] > $serverTime) { return false; } //建立時間錯誤 if (isset($payload['exp']) && $payload['exp'] < $serverTime) { return false; } //已失效 return $payload; }