JSON Web Token(JWT)是目前最流行的跨域身份驗(yàn)證解決方案蒿涎。直接根據(jù)token取出保存的用戶信息蜕便,以及對(duì)token可用性校驗(yàn)签赃,大大簡(jiǎn)化單點(diǎn)登錄溃斋。
JWT=header+payload+signature(以.相隔)
例:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1NzYxMTk2NTYsInVzZXJuYW1lIjoiemRqIiwicGFzc3dvcmQiOiIxMjMifQ.ud_qtIYt3QywJkmjPZIXVPaW3SnWCFj9dLVYa7iTEIg
下面詳細(xì)介紹一下每個(gè)部分界拦。
頭部(Header)
用于描述關(guān)于該JWT的最基本的信息,例如其類型以及簽名所用的算法等盐类。
{"alg":"HS256","typ":"JWT"}
BASE64編碼后為:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
載荷(playload)
(1)標(biāo)準(zhǔn)中注冊(cè)的聲明(建議但不強(qiáng)制使用)
(2)公共的聲明
(3)私有的聲明(過(guò)期時(shí)間寞奸,用戶名等信息)
{"exp":1576119656,"username":"zdj","password":"123"}
BASE64編碼后:eyJleHAiOjE1NzYxMTk2NTYsInVzZXJuYW1lIjoiemRqIiwicGFzc3dvcmQiOiIxMjMifQ
簽名(signature)
header(base64)+payload(base64)使用.連接組成的字符串,然后通過(guò)header中聲明的加密方式進(jìn)行加鹽secret組合加密在跳,然后就構(gòu)成了jwt的第三部分
ud_qtIYt3QywJkmjPZIXVPaW3SnWCFj9dLVYa7iTEIg
注:secret是保存在服務(wù)器端的簽名私鑰,就是我們今天的主角隐岛;
基于java實(shí)現(xiàn)JWT:
生成token:
public static String Generatetoken(String username, String password) {
String token = "";
try {
// 過(guò)期時(shí)間
Date date = new Date(System.currentTimeMillis() + EXPIRE_DATE);
// 秘鑰及加密算法
Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET);
// 設(shè)置頭部信息
Map<String, Object> header = new HashMap<String, Object>();
header.put("typ", "JWT");
header.put("alg", "HS256");
// 攜帶username猫妙,password信息,生成簽名
token = JWT.create().withHeader(header)
.withClaim("username", username)
.withClaim("password", password).withExpiresAt(date)
.sign(algorithm);
} catch (Exception e) {
e.printStackTrace();
return null;
}
return token;
}
校驗(yàn)token:
public static boolean verify(String token) {
try {
Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET);
JWTVerifier verifier = JWT.require(algorithm).build();
System.out.println("驗(yàn)證token:" + token);
DecodedJWT jwt = verifier.verify(token);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
生成的token為
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1NzYxMTk2NTYsInVzZXJuYW1lIjoiemRqIiwicGFzc3dvcmQiOiIxMjMifQ.ud_qtIYt3QywJkmjPZIXVPaW3SnWCFj9dLVYa7iTEIg
綜上聚凹,我們要偽造token割坠,首先要拿到TOKEN_SECRET,才可以偽造簽名妒牙,token才能校驗(yàn)通過(guò)彼哼。
pyjwt 庫(kù),可通過(guò) jwt.decode(jwt_str, verify=True, key=key_)
進(jìn)行簽名校驗(yàn)湘今,但導(dǎo)致校驗(yàn)失敗的因素不僅密鑰錯(cuò)誤敢朱,還可能是數(shù)據(jù)部分中預(yù)定義字段錯(cuò)誤(如,當(dāng)前時(shí)間超過(guò) exp),也可能是 JWT字符串格式錯(cuò)誤等等拴签,所以孝常,借助 jwt.decode(jwt_str, verify=True, key=key_) 驗(yàn)證密鑰 key_:
1.若簽名直接校驗(yàn)失敗,則 key_ 為有效密鑰蚓哩;
2.若因數(shù)據(jù)部分預(yù)定義字段錯(cuò)誤
(jwt.exceptions.ExpiredSignatureError,
jwt.exceptions.InvalidAudienceError,
jwt.exceptions.InvalidIssuedAtError,
jwt.exceptions.InvalidIssuedAtError,
jwt.exceptions.ImmatureSignatureError)導(dǎo)致校驗(yàn)失敗构灸,說(shuō)明并非密鑰錯(cuò)誤導(dǎo)致,則 key_ 也為有效密鑰岸梨;
3.若因密鑰錯(cuò)誤(jwt.exceptions.InvalidSignatureError)導(dǎo)致校驗(yàn)失敗喜颁,則 key_ 為無(wú)效密鑰;
4.若為其他原因(如曹阔,JWT 字符串格式錯(cuò)誤)導(dǎo)致校驗(yàn)失敗洛巢,根本無(wú)法驗(yàn)證當(dāng)前 key_ 是否有效。
按此邏輯次兆,快速實(shí)現(xiàn) JWT 密鑰暴破功能稿茉,代碼如下:
準(zhǔn)備好key.txt字典,目標(biāo)token為:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1NzYxMjE1NDcsInVzZXJuYW1lIjoiemRqIiwicGFzc3dvcmQiOiIxMjMifQ.mkCLR5Kje9x-z8hRgWBMxnQm8hknOwV1Zd8uSZa3rQY芥炭,運(yùn)行腳本進(jìn)行爆破:
總結(jié)
因此漓库,開發(fā)員要十分注意token的密鑰強(qiáng)度,不然攻擊者可以通過(guò)pyjwt爆破得到token密鑰园蝠,通過(guò)header和payload進(jìn)行signature渺蒿,進(jìn)而偽造token發(fā)生跨域攻擊。