偶然的机会发现在参数相同情况下利用Python(pyjwt)生成的JWT和JAVA服务返回的不同:
Java依赖:
io.jsonwebtoken jjwt0.9.1
注意到Java中使用setHeader()和setPayload()方法生成的token和Python中pyjwt的一致。
.....// 此处省略n行
JwtBuilder builder = Jwts.builder()
.setClaims(payload)
// .setHeader(header)
// .setPayload(payload)
.signWith(signatureAlgorithm, salt);
return builder.compact(); //开始压缩为***.***.***格式的JWT
}
但使用setClaims()时无法达到与pyjwt的加密一致性,以下是setClaims的相关说明:
JwtBuilder setClaims(Mapclaims);
至此略有眉目,Python应该是通过json.dumps()直接序列化为plaintext string的。
后面通过对解密过程进行追踪,发现Java中对JWT的header部分做了个性化处理:
public JwtBuilder signWith(SignatureAlgorithm alg, String base64EncodedSecretKey) {
Assert.hasText(base64EncodedSecretKey, "base64-encoded secret key cannot be null or empty.");
byte[] bytes = TextCodec.base64.decode(base64EncodedSecretKey);
return signWith(alg, bytes);
}
其中的TextCodec.base64.decode(base64EncodedSecretKey);解密成bytes的操作与Python中base64.decodebytes()相对应;
从两个方面解决均可:
Java方面妥协:
Java中使用setHeader()和setPayload()方法进行加密;Python方面妥协:
Python中对salt进行处理
j_salt = base64.decodebytes(salt.encode('utf-8'))
之后再进行操作。例如:原来是这样:
sign = base64.urlsafe_b64encode(hmac.new(salt, first_second.encode('utf-8'), hashlib.sha512).digest()).decode('utf-8').replace('=', '')
修改为:
sign = base64.urlsafe_b64encode(hmac.new(j_salt, first_second.encode('utf-8'), hashlib.sha512).digest()).decode('utf-8').replace( '=', '')



