代码之家  ›  专栏  ›  技术社区  ›  Saurabh Tiwari

JWT令牌在解析时总是作为过期令牌接收

  •  0
  • Saurabh Tiwari  · 技术社区  · 6 年前

    我正在我的一个应用程序中使用JWT Authentictaion以及Spring引导/安全性,这是我第一次使用JWT。

    static void addAuthentication(HttpServletResponse res, JWTPayload payload) {
        // all authentication related data like authorities and permissions can be 
        // embed to the token in a map using setClaims()
        Map<String, Object> claims = new HashMap<String, Object>();
        claims.put("roles", payload.getRoles());
        claims.put("permissions", payload.getPermissions());
        String JWT = Jwts.builder()
            .setSubject(payload.getUsername())
            .setClaims(claims)
            .setExpiration(new Date(System.currentTimeMillis() + EXPIRATIONTIME))
            .signWith(SignatureAlgorithm.HS512, SECRET_KEY)
            .compact();
        res.addHeader(HEADER_STRING, TOKEN_PREFIX + " " + JWT);
      }
    
    
      /**
       * this method retrives the token from the header and validates it.
       * this method is called from the JWTAuthentication filter which is
       * used against all the incoming calls except the login.
       * @param request
       * @return
       */
      static Authentication getAuthentication(HttpServletRequest request) {
        String token = request.getHeader(HEADER_STRING);
        if (token != null) {
          // parse the token.
          String user = Jwts.parser()
              .setSigningKey(SECRET_KEY)
              .parseClaimsJws(token.replace(TOKEN_PREFIX, ""))
              .getBody()
              .getSubject();
    
          return user != null ?
              new UsernamePasswordAuthenticationToken(user, null, emptyList()) :
              null;
        }
        return null;
      }
    

    JWT在头文件中生成和接收得很好。但是,如果在随后的API调用中使用,我将收到以下错误。

    io.jsonwebtoken.ExpiredJwtException: JWT expired at 2018-10-31T16:06:05Z. Current time: 2018-10-31T16:06:08Z, a difference of 3421 milliseconds.  Allowed clock skew: 0 milliseconds.
    

    异常表示允许的时钟偏移为0毫秒。在我上面的代码中 EXPIRATIONTIME 设置为30000(我相信这是以秒为单位设置的)。我也尝试过增加这个值,但仍然得到错误。

    请说明我做错了什么?

    1 回复  |  直到 6 年前
        1
  •  0
  •   Prasann    6 年前

    不确定你是否已经得到了答案,但有人可能会从中受益。一开始我也有同样的问题,我认为这是JWT的问题。但是,当我调试我的代码时,我知道我犯了一个愚蠢的错误,过期日期是在过去设置的。

    import java.security.Key;
    import java.util.Calendar;
    import java.util.HashMap;
    import java.util.Locale;
    import java.util.Map;
    import java.util.UUID;
    
    import javax.crypto.spec.SecretKeySpec;
    import javax.xml.bind.DatatypeConverter;
    
    import io.jsonwebtoken.Claims;
    import io.jsonwebtoken.Jws;
    import io.jsonwebtoken.Jwts;
    import io.jsonwebtoken.SignatureAlgorithm;
    
    public class TestJWTToken {
        private static final String API_KEY = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    
        public static void main(String... args) {
            String jwt = createJWT();
            System.out.println("JWT: " + jwt);
            parseJWT(jwt);
        }
    
        private static String createJWT() {
            Calendar cal = Calendar.getInstance(Locale.UK);
            Calendar cal1 = Calendar.getInstance(Locale.UK);
            cal1.setTime(cal.getTime());
            cal1.add(Calendar.SECOND, 300);
    
            byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(API_KEY);
            Key signingKey = new SecretKeySpec(apiKeySecretBytes, SignatureAlgorithm.HS256.getJcaName());
    
            Map<String, Object> map = new HashMap<>();
            map.put("alg", "HS256");
            map.put("typ", "JWT");
    
            String someId = UUID.randomUUID().toString();
    
            return Jwts.builder().setHeader(map).setIssuer("service_provider").setSubject("consumer_provider_connectivity_token")
                    .claim("some_id", someId).setIssuedAt(cal.getTime()).setExpiration(cal1.getTime())
                    .signWith(SignatureAlgorithm.HS256, signingKey).compact();
        }
    
        private static void parseJWT(String jwt) {
            Jws<Claims> jwsClaims = Jwts.parser().setSigningKey(DatatypeConverter.parseBase64Binary(API_KEY)).parseClaimsJws(jwt);
            System.out.println("JWT decoded: " + jwsClaims);
    
            Claims claims = jwsClaims.getBody();
            System.out.println("Subject: " + claims.getSubject());
            System.out.println("Issuer: " + claims.getIssuer());
            System.out.println("Issued at: " + claims.getIssuedAt());
            System.out.println("Expiration: " + claims.getExpiration());
            System.out.println("Some_Id: " + claims.get("some_id"));
        }
    }