【问题标题】:Android JWT parsing payload/claims when signedAndroid JWT 在签名时解析有效负载/声明
【发布时间】:2016-05-02 03:09:49
【问题描述】:

我有一个从服务器获得的签名 JWT 字符串。我不知道密钥,或者我不想将密钥放在客户端/设备上。

当使用我的令牌使用此站点时:https://jwt.io/ 我得到了所需的结果,它告诉我标头和有效负载信息。

我在 android 上找不到一个库可以做这个网站的工作,我已经尝试了所有我能找到的库。最认可使用的是:https://github.com/jwtk/jjwt

但这给了我一个例外,我无法解析签名令牌,正如上面其他网站所证明的那样,这是错误的。我使用的另一个资源是:https://bitbucket.org/b_c/jose4j/wiki/Home

这至少给了我我所能得到的最远的标题信息。

为了说明为什么会这样,有效负载包含一个过期时间,并且在设备上,当令牌即将过期时,我应该提示用户重新输入他们的凭据以获取新令牌。现在这似乎是一个安全威胁,因为黑客可以操纵设备上的令牌,但服务器会检查令牌以确保它是真实的,这就是为什么我不想要设备上的密钥,因为这可以被黑客,并使整个应用程序易受攻击。

【问题讨论】:

    标签: java android security jwt


    【解决方案1】:
    Jwt 的

    parseClaimsJwt() 方法需要签名。所以,正确的做法是:

    String jws = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ";
    int i = jws.lastIndexOf('.')
    String withoutSignature = jws.substring(0, i+1);
    
    Claims claims = (Claims) = Jwts.parser().parse(withoutSignature).getBody();
    

    【讨论】:

      【解决方案2】:

      如果您想在不使用签名的情况下解析签名文本:

      1- 添加以下依赖项:

      //JWT
      compile 'io.jsonwebtoken:jjwt:0.7.0'
      

      2 - 添加以下导入:

      import io.jsonwebtoken.Claims;
      import io.jsonwebtoken.Header;
      import io.jsonwebtoken.Jwt;
      import io.jsonwebtoken.Jwts;
      

      3- 使用下面的代码块:

      //ref : https://github.com/jwtk/jjwt/issues/135
      //you can put your signatured text instead of jws variable.
      String jws = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ";
      int i = jws.lastIndexOf('.')
      String withoutSignature = jws.substring(0, i+1);
      Jwt<Header,Claims> untrusted = Jwts.parser().parseClaimsJwt(withoutSignature);
      /*untrusted.getBody().getSubject();
        untrusted.getBody().getExpiration();
        etc.
      */
      

      【讨论】:

      • 是的,这行得通。但不是 Jwt
        untrusted = Jwts.parser().parseClaimsJwt(withoutSignature);我们可以使用 Claims untrusted = Jwts.parser().parseClaimsJwt(withoutSignature).getBody();
      • 工作示例。我能够从令牌中提取声明。谢谢!
      【解决方案3】:

      您可以使用jose4j's JWT consumer 仅进行解析而不检查声明或签名。类似以下的内容将解析令牌并将过期时间与当前时间进行比较,以查看它是否已过期。

      String jwt = "eyJhbGciOiJIUzI1NiJ9" +
              ".eyJzdWIiOiIxMjM0NTY3ODkwIiwiZXhwIjoxNDUzODE0NjA0LCJuYW1lIjoiSm9obiBEb2UifQ" +
              ".IXcDDLXEpGN9Po5C-Mz88jUCNYrHxu6TVJLavf0NgT8";
      
      JwtConsumer consumer = new JwtConsumerBuilder()
              .setSkipAllValidators()
              .setDisableRequireSignature()
              .setSkipSignatureVerification()
              .build();
      JwtClaims claims = consumer.processToClaims(jwt);
      NumericDate expirationTime = claims.getExpirationTime();
      
      if (NumericDate.now().isAfter(expirationTime))
      {
          System.out.println("Token expired at " + expirationTime);
      }
      else
      {
          System.out.println("Token is still good until " + expirationTime);
      }
      

      【讨论】:

        【解决方案4】:

        答案很简单,尽管我认为应该在框架中。但是一个简单的未签名的 JWT 仍然有 2 个必需的句点,但在最后一个之后没有任何内容,所以我将我的 JWT 拆分为句点,并将第一个和第二个与句点结合起来,并在最后加上一个句点。

        String[] splitToken = result.Value.Content.AuthorizationJWTToken.split("\\.");
        Jwt parsedToken = Jwts.parser().parse(splitToken[0] + "." + splitToken[1] + ".");
        

        这是使用https://github.com/jwtk/jjwt 库。

        【讨论】:

          猜你喜欢
          • 2015-10-30
          • 2020-09-18
          • 2017-02-10
          • 2018-08-06
          • 1970-01-01
          • 2019-02-11
          • 2020-09-18
          • 2016-03-12
          • 1970-01-01
          相关资源
          最近更新 更多