使用原生 JS 語法將 JWT exp 日期轉換成正常時間
前言
JWT(Json Web Token
) 目前已廣泛應用了,可以很方便地用於無狀態協議(stateless
)的 http api 使用
而簽出後,自帶 iat(issue at
,發出日期)、exp(expires
,有效日) 便於前端判斷 token 有效期限
本身又是單純以 base64 編碼,故 Client 端可以很輕鬆的解回來查看相關資訊( jwt 官方建議不應在 token 裡埋藏太多資訊)
解回來後,會發現iat
, exp
日期都是以純數字保存,需再做一層日期轉換,才能取得正確時間
將JWT iat, exp 轉換回正常時間(純js)
npm 上其實有不少現成套件(如jwt-decode
)可以直接轉換回來
但對前端來說,本身就有現成的語法,其實不太需要特地再下載一個套件
僅須短短2行程式碼即可取得時間,也可以讓前端更輕量些!
(亦可精簡成一行,只是較不易閱讀)
const payload = JSON.parse(atob(token.split('.')[1]));
const expDate = new Date(new Date(0).setUTCSeconds(payload.exp)); // 得到正常的js日期時間
補充說明:btoa
(binary to ascii, 編碼)、atob
(ascii to binary, 解碼)是瀏覽器提供的base64編碼、解碼的函式(Web API)
補充:使用dayjs
判斷 token 是否到期並取得新的 token(Angular)
由於moment.js
作者已宣佈不維護,加上後起之秀dayjs
興起,僅2kb大小的日期處理套件!
現在前端比較流行的應是dayjs
了
若仍是使用moment.js
也沒關係,用法基本上一樣!
提供 Angular 範例
使用dayjs
判斷 token 是否到期,若接近到期,則取得新 token
import * as dayjs from 'dayjs';
// 須依自己在jwt放入的資料調整interface格式
interface JwtPayload {
username: string;
sub: string;
iat: number;
exp: number;
}
// ....
// 省略 Angular class部份,僅貼上 function
// ...
private refreshToken(token: string): void {
const payload: JwtPayload = JSON.parse(atob(token.split('.')[1])) as JwtPayload;
const expDate = dayjs(new Date(0).setUTCSeconds(payload.exp)); // 僅將最外層的`new Date`改成`dayjs`即可無痛轉換成`dayjs`格式
const current = dayjs();
if (current.isAfter(expDate.subtract(5, 'minutes'))) {
this.http.get<{token: string}>(`/api/refresh/token`).subscribe({
next: res => this.saveToken(res.token), // 將 token 更新回 Angular 的 authService 與 localStorage 或 cookie,依需求自行調整
error: (err: HttpErrorResponse) => console.log(err)
});
}
參考資料
Stack Overflow / Transform Tick to Date in JS
程式前沿 / JavaScript用btoa和atob來編碼解碼Base64