前言:
在我百寶箱中,JWT不常用,但幾乎每個實做都用了,因為JWT基本上已經嵌入在.NET中開箱即用了。😁
說明:
我一般會形容JWT是鑰匙,你通過了認證並授權後,就發給你一把鑰匙,拿著鑰匙就有權限進行操作,這把鑰匙可以有時效,也可以沒有時效,端看需求。
JWT是標準,有標準格式,它標準格式分成3段,每段用.隔開,第二段和第三段是重點,第二段放了所有資訊,JWT標準中規範了必要和可選的資訊,必要的包括sub(subject), iss(issuer), exp(expired), nbf(NotBeFore), iat(IssueAt)。
其中必要中的必要是exp,這個標記了JWT的到期時間。
JWT沒有明確規定時間是哪種Timestamp,但一般用UTC。
第三段則是第二段的簽章,用加密算法把第二段用特定密碼算一個簽章放第三段,因此第二段 + 密碼計算簽章後,必定等於第三段,如果不等於,就是被竄改了。第三段的JWT規範是BASE64。
目前的登入Token,幾乎都用JWT,.NET c# 直接做好JWT中間件,套用即可,基本上是業界標準了。
JWT的第二段資訊顯然是關鍵,第二段資訊稱為Payload,是json用BASE64編碼後的字串。
這裡畫重點,是BASE64編碼後的字串,這表示它沒有加密,JWT不具備加密功能,只具備簽章功能,能夠驗證JWT是否合法沒被竄改,而根據合法JWT,則可以判斷是否過期,並根據sub(Subject)判斷持有者是不是本人,根據iss(Issuer)判斷簽發者是不是授權簽發者。
特殊用法:
既然我們知道JWT是根據第二段的Payload紀錄資訊,Payload本身是json,那我們完全可以自行設計非標準的JWT格式,對吧!?
在c#/Java中,我們只需要建立一個Model,我一般取名為AuthToken,裡面參考JWT放入sub,iss,exp,iat,nbf。
使用時
var token = new AuthToken() { sub = "{user}",
iss = "{BestServer}",
exp = now + 1440 timestamp,
iat = now timestamp,
nbf = now - 5secs timestamp
}
var SpecifyJWT = AESCipher.Encrypt(token.toJson());
打完收工。
當然,檢查一樣,反過來,先用AESCipher解密,接著依序檢查 exp, nbf 。
一個具有加密效果的AccessToken就完成了,如果原本用c# JWT中間件,那只要實做一個自己的中間件替換上去,就完成高強度客製化的認證Token設計了。
JWT用法:
實務上,我常用JWT系列,因為它是分散式的,不受限Session,任何後端都能檢核。
但它可以有幾種變種:
- 後端統一用一台認證服務簽發和檢核JWT,所有服務都先把Client端JWT送來檢核,變成認證授權與服務分離
- 後端服務都使用同一個Jwt工具包進行簽發和檢核
- 資料庫中設計黑名單,特定JWT寫入黑名單後失效,新認證不予簽發JWT
- 資料庫中設計白名單,所有JWT簽發後都寫入資料庫,檢核時查找資料庫,如果使用者異常,從資料庫中刪除或註記這筆JWT,新認證不予簽發JWT,這種做法等同於把JWT當作AccessToken使用,差別是,AccessToken較短,通常是隨機字串,沒有隱含資訊,JWT則比較長,但有隱含資訊
















