JWT(JSON Web Token)

1 篇文章 / 0 new
author
JWT(JSON Web Token)
自從RESTful架構興起後,越來越多人提倡使用JWT來取代傳統Session
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;
}
Free Web Hosting