Токен jwt всегда получается как просроченный во время синтаксического анализа

Я использую JWT Authentictaion в одном из своих приложений вместе с Spring Boot / Security и его первым подходом к 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 (я считаю, что это установлено в секундах). Я тоже пытался увеличить это значение, но все равно получаю сообщение об ошибке.

Подскажите, пожалуйста, что я делаю не так?

0
0
4 054
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Не уверен, что вы уже получили ответ, но когда-нибудь кому-то это может пригодиться. Первоначально у меня была такая же проблема, и я подумал, что это проблема с 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"));
    }
}

Я попробовал код, и это не помогло. Я вижу, вы использовали Calendar API, чтобы исправить дату, а не добавлять миллисекунды. Вы хотели упомянуть какие-либо другие изменения?

Saurabh Tiwari 14.01.2019 07:52

Вы предполагаете, что EXPIRATIONTIME установлен в секундах, но в соответствии с вашим кодом вы создаете Date с помощью System.currentTimeMillis(), который использует миллисекунды, а не секунды. Итак, когда вы добавляете EXPIRATIONTIME к System.currentTimeMillis(), он обрабатывается как миллисекунды, а не как секунды. Я пробовал использовать ваш код, и JWT, созданный с помощью вашего кода, действителен в течение 30 секунд, что соответствует вашему коду. Если вы хотите установить его на 30000, вам нужно установить EXPIRATIONTIME на 30000000

Prasann 18.01.2019 12:28

Другие вопросы по теме