在客户端上,您正在构建 JWT,例如:
byte[] key = getSignatureKey();
String jwt = Jwts.builder().setIssuer("myTestApplication")
.setSubject("myTest")
.setExpiration(expirationDate)
.put("scope", "testing")
.signWith(SignatureAlgorithm.HS256, key)
.compact();
在服务器端,您可以验证 JWT 的密钥和到期日期 exp
(以及更多,即创建日期、发行iss
者、受众aud
):
String subject = "notMyToken";
try {
Jws jwtClaims = Jwts.parser().setSigningKey(key).parseClaimsJws(jwt);
subject = claims.getBody().getSubject();
//OK, we can trust this JWT
} catch (SignatureException e) {
//don't trust the JWT!
}
应该通过使用 SSL 来避免窃取 JWT,...但是如果 JWT 被窃取,就会有重放这个 JWT 的风险——对。这就是jti
进来的地方。
jti (JWT ID) 声明为 JWT 提供唯一标识符。标识符值的分配方式必须确保相同的值被意外分配给不同的数据对象的概率可以忽略不计;如果应用程序使用多个发行者,则必须防止不同发行者产生的值之间的冲突。jti 声明可用于防止 JWT 被重放。jti 值是区分大小写的字符串。使用此声明是可选的。
使用此标识符,您可以识别此 ID 是否已发送(您必须在服务器端将其列入黑名单,这会以某种方式破坏 JWT 的性质)。因为您应该使用到期日期,所以如果到期日期导致 SignatureException,您可以清除 ID。
但是,如果“黑客”从数据库中窃取了 JWT,正如您在问题中所写的那样,除了被盗的 JWT 之外,您可能还有其他问题,因为攻击者还可以窃取其他数据等。
希望这会有所帮助。