4

我有一个关于 JSON Web Token (JWT) 的一般性问题。

如果 JWT 通过黑客攻击或物理访问从客户端被盗(例如,它被存储为 cookie 或应用程序的数据库),它可以用于发送到服务器,服务器会认为它是合法用户。这个对吗?

是否有任何常见或标准的做法来防止这种情况发生,例如,通过从客户端一起发送设备/浏览器的类型或一些参考代码,服务器检查它是否与生成和存储 JWT 令牌的附加数据相匹配。(但是,我读到标准做法是不在服务器上存储任何内容。)

请告知,因为我需要实现 Java JWT (JJWT)、RESTful Java Jersey 和 Google Web Toolkit。(我一直在阅读这样的文档:[ https://stormpath.com/blog/where-to-store-your-jwts-cookies-vs-html5-web-storage])。

谢谢!

4

2 回答 2

8

拥有 JWT 是身份验证的证明。窃取令牌的攻击者可以冒充用户。

因此,请确保令牌安全:

  • 使用 TLS 通道
  • 根据存储类型添加额外的安全措施。Cookie 容易受到 CSRF 攻击。如果您不需要从 javascript 访问令牌,请使用 HttpOnly。LocalStorage 容易受到 XSS 攻击
  • 在身份验证令牌上设置较短的过期时间,如果令牌过期则需要凭据

黑名单没有用,因为您不会知道 JWT 已被盗。并且它的使用打破了状态性,这是 JWT 的优势之一

此外,可以将 IP 添加到令牌中,但请考虑使用场景,因为它在移动设备或代理后面的系统上可能会出现问题

于 2017-01-21T18:01:03.260 回答
2

在客户端上,您正在构建 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 之外,您可能还有其他问题,因为攻击者还可以窃取其他数据等。

希望这会有所帮助。

于 2017-01-21T13:46:21.330 回答