JSON Web Token(JWT)

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])。
谢谢!
2个回答

8
拥有JWT是身份验证的证明。偷走令牌的攻击者可以冒充用户。
因此,要保护好令牌:
- 使用TLS通道 - 根据存储类型添加额外的安全措施。Cookie容易受到CSRF攻击。如果不需要从JavaScript访问令牌,请使用HttpOnly。LocalStorage容易受到XSS攻击。 - 对身份验证令牌设置短暂的过期时间,并在令牌过期时要求重新输入凭据。
黑名单不起作用,因为您不会知道JWT是否被盗。而且它的使用会破坏JWT的无状态性,这是JWT的优点之一。
此外,可以将IP添加到令牌中,但考虑使用场景,因为在移动设备或代理后面的系统上可能会有问题。

比我的回答更好 :-) - mxlse
1
您还可以添加一些浏览器指纹(例如User-Agent和Accept-*标头)。同时使用2个cookie,其中一个是SameSite cookie,并且对于所有敏感操作都是必需的(csrf仍然可以窃取数据,但无法操纵它们)。 - Thomas Broyer
因此,服务器生成的令牌由服务器进行数字签名并提供给客户端,以便当令牌返回到服务器时,服务器将识别它是其生成的令牌。但是,服务器无法百分之百确定它是相同的客户端。服务器只能百分之百确定它生成了令牌。因此,如其他评论中所述,在客户端(客户端IP地址、客户端浏览器指纹等)需要保证是相同的客户端,但在某些用例中会出现问题,例如代理或移动电话。我的理解正确吗? - daparic
1
当JWT被发行时,可以根据使用渠道、设备(浏览器、移动设备、桌面)或基础架构添加额外的安全手段。并没有什么神奇的解决方案... - pedrofb

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之外的其他问题,因为攻击者也可能窃取其他数据等。
希望这对您有所帮助。

想知道 jti 字段是否用于强制令牌仅被使用一次? - William Ross

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接