【问题标题】:JSON Web Token (JWT)JSON 网络令牌 (JWT)
【发布时间】:2017-06-06 08:54:16
【问题描述】:

我有一个关于 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])。

谢谢!

【问题讨论】:

    标签: gwt jwt jersey-2.0 json-web-token jjwt


    【解决方案1】:

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

    因此,请确保令牌安全:

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

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

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

    【讨论】:

    • 比我的答案更好:-)
    • 您还可以添加一些浏览器指纹(例如 User-Agent 和 Accept-* 标头)。还使用 2 个 cookie,其中一个是 SameSite cookie,所有敏感操作都需要(csrf 仍然可以窃取数据,但不能操纵它们)
    • 所以服务器生成的令牌由服务器进行数字签名并提供给客户端,这样当令牌返回服务器时,服务器将识别它是它生成的令牌。但是,服务器不能 100% 确定它是同一个客户端。服务器仅 100% 确定它生成了令牌。因此,正如其他 cmets 所述,客户端(客户端 IP 地址、客户端浏览器指纹等)需要保证它是同一个客户端,但随后会在某些用例(例如代理或手机)上中断。我的理解正确吗?
    • 这是正确的@ifelsemonkey。当 JWT 发布时,可以根据使用渠道、设备(浏览器、移动设备、桌面)或基础设施添加额外的安全手段。没有灵丹妙药……
    【解决方案2】:

    在您正在构建 JWT 的客户端上,例如:

    byte[] key = getSignatureKey();
    
    String jwt = Jwts.builder().setIssuer("myTestApplication")
        .setSubject("myTest")
        .setExpiration(expirationDate)
        .put("scope", "testing") 
        .signWith(SignatureAlgorithm.HS256, key)
        .compact();
    

    在服务器端,您可以验证 JWT 关于 key到期日期 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 字段是否用于强制令牌只使用一次?
    猜你喜欢
    • 1970-01-01
    • 2016-08-01
    • 2019-08-08
    • 2017-09-03
    • 1970-01-01
    • 2016-07-20
    • 1970-01-01
    • 1970-01-01
    • 2023-03-16
    相关资源
    最近更新 更多