標籤:copy 多個 charset set 使用 body for uri ram
JSON Web Token(JWT) - 實現系統整合授權訪問
這是一個第三方系統訪問AnyReport報表系統使用JWT授權的實現案例,AnyReport報表系統暴露報表資源URL供第三方系統訪問,
第三方系統可以使用iframe,src設定為報表連結訪問報表資源,這時資源URL類似restful api需要被認證的系統才能訪問,
通過JWT的好處是不需要做登入認證在伺服器端建立session。
JWT組成部分
JSON web Token 簡稱JWT,是一種token的URL安全方法,用於在網路通訊的雙方之間傳遞
JWT傳輸內容是由頭部 header、負載 payload、簽名 signature 三部分組成
header 定義Token 類型、加密類型,告訴伺服器端使用的加密方法是HmacSHA256(HS256)
1234 |
{ "typ" : "JWT" , "alg" : "HS256" } |
負載 payload 定義一些需要使用的資訊:用戶端ID、JWT建立的時間、使用者ID,負載中不需要傳輸敏感資訊如密碼、密鑰等,JWT內容通過HTTP傳輸不安全。
12345 |
{ "cid" : "OA0001" , "iat" : 1482656248798, "uid" : "admin" } |
cid:是第三方系統的標示,因為可能多個第三方系統訪問報表系統,報表系統可以根據cid查詢密鑰、失效時間等做JWT內容驗證。
iat:建立JWT的時間,伺服器端根據該iat判斷JWT是否已經失效了,防止連結被別人擷取。
uid:使用者ID,伺服器端可以根據該使用者查詢一些使用者相關的資訊,如一些許可權資訊,這個案例並沒有使用這個欄位。
簽名 signature 部分是使用金鑰組header Base64與payload Base64加密的Base64字串。
JWT三個部分使用“.”連結的字串, 最終JWT是:header base64字串 + payload base64 字串 + HmacSHA256(headerBase64 + "." + payloadBase64) base64字串
1 |
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJjaWQiOiJPQTAwMDEiLCJpYXQiOjE0ODI2NTcyODQyMjF9.TeJpy936w610Vrrm+c3+RXouCA9k1AX0Bk8qURkYkdo= |
JWT產生方法
JWT是由第三方系統產生的,可以使用伺服器端語言,也可以使用Javascript產生,這種方式是最簡單的,密鑰儲存在第三方系統伺服器端當進入頁面可以將密鑰給js, js擷取密鑰而產生JWT,這裡第三方系統密鑰與報表系統密鑰一致,各保留一份無需傳輸。
12345678910111213 |
function token() { var base64 = new Base64(); //網上尋找一個base64庫 var header= ‘{"typ":"JWT","alg":"HS256"}‘ ; var headerBase64 = base64.encode(header); //header base64字串 var date = new Date(); var payload = ‘{"cid" : "OA0001","iat" : 1482656248798,"uid" : "admin"}‘ ; var payloadBase64 = base64.encode(payload); //payload base64字串 var base64Token = headerBase64 + "." + payloadBase64; var signature = CryptoJS.HmacSHA256(base64Token, "123456" ); //使用google的hmac-sha256.js庫 var signatureBase64 = base64.hex2b64(signature.toString()); var jwt = base64Token + "." + signatureBase64; return jwt; } |
產生的base64的token作為URL請求資源,url還需要做urlencoding編碼
12 |
//url?jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJjaWQiOiJPQTAwMDEiLCJpYXQiOjE0ODI2NTcyODQyMjF9.TeJpy936w610Vrrm%2Bc3%2BRXouCA9k1AX0Bk8qURkYkdo%3D url?jwt=encodeURIComponent(token()); |
JWT驗證
驗證是在報表系統伺服器端進行,驗證部分比較簡單的,採用Java解析JWT並做驗證, 首選將jwt按“.“分割為parts三部分header,payload、signature, 使用js相同的密鑰如“123456”進行加密,得到加密結果與jwt的signature進行比較,如果相等表示驗證通過。
123456789101112131415161718192021222324252627 |
public static boolean verify(String jwt) { String[] parts = jwt.split( "\\." ); String payload = StringUtils.newStringUtf8(Base64.decodeBase64(parts[ 1 ])); JSONObject json = JSONObject.fromObject(payload); String clientId = json.getString( "cid" ); long iatTime = json.getLong( "iat" ); //驗證jwt是否失效 if (System.currentTimeMillis() - iatTime > 3600 * 1000 ) { return false ; } //驗證簽名 signature byte [] content = (parts[ 0 ] + "." + parts[ 1 ]).getBytes(StandardCharsets.UTF_8); byte [] signature = Base64.decodeBase64(parts[ 2 ]); try { return verifySignatureFor( "HmacSHA256" , "123456" , content, signature); } catch (Exception e) { throw new RuntimeException(e); } } public static boolean verifySignatureFor(String algorithm, String secret, byte [] contentBytes, byte [] signatureBytes) throws Exception { byte [] secretBytes = secret.getBytes(StandardCharsets.UTF_8); Mac mac = Mac.getInstance(algorithm); mac.init( new SecretKeySpec(secretBytes, algorithm)); return MessageDigest.isEqual(mac.doFinal(contentBytes), signatureBytes); } |
?2017 中普軟體 All Rights Reserved.
json web token 網上學習筆記