私が使用していますjjwt
JWTトークン作成のために。ローカルシステム時間、すなわちと有効期限を設定するときにすべてが正常に動作します
;日付EXPDATEは、新しい日付(新しい日付()getTime()+ 180000)を= //java.util.Date
しかし、私はUTC形式の日時を使用してみましたし、同じ3分の有効期限とJWTトークンに署名しました。そして今、それは投げてExpiredJwtException
も、私が検証をできるだけ早くトークンを作成していますけれども。私は、UTCにタイムゾーンを設定するためのSimpleDateFormatを使用しています。これは、Javaでjjwtを使用してトークン作成するための私のコードです:
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date expDate, issDate;
try {
expDate = (Date) simpleDateFormat.parse(sdf.format(new Date().getTime() + 180000));
issDate = (Date) simpleDateFormat.parse(sdf.format(new Date().getTime()));
JwtBuilder builder = Jwts.builder()
.setExpiration(expDate)
.setIssuedAt(issDate)
.setId(id)
.signWith(signingKey, signatureAlgorithm);
jwtToken = builder.compact();
} catch (ParseException ex) {
}
トークンが正常に作成されます。私もオンライン内容を確認することができます。EXPDATEはissDateの3分進んでいます。私もそれがトークンを作成することを渡すことによって作成された後にできるだけ早くトークンを検証するためのメソッドを呼び出しています。私の検証方法があります。
try {
Jwts.parser().setSigningKey(signingKey).parseClaimsJws(token);
log.info("jwt verification success");
} catch (ExpiredJwtException exJwt) {
log.info("expired jwt : \n{}", exJwt.getMessage());
} catch (JwtException e) {
log.info("tampered jwt");
}
しかし、私は取得していますExpiredJwtException
。エラーがあります
JWT期限切れ:JWTは2019-05-17T01で期限切れ:24:48Zを。現在時刻:2019-05-17T07:06:48Z、20520836ミリ秒の違い。許可されたクロック・スキュー:0ミリ秒。
私のログから、この時点で私のトークンで発行日と有効期限は次のとおりです。
issued date is: 2019-05-17T07:06:48.000+0545
expiry date is: 2019-05-17T07:09:48.000+0545
これはどのように起こっているのでしょうか?そして、あなたの助けをありがとうございました。
必要ありませんSimpleDateFormat
、ここでは、Date
からのミリ秒数を表しUNIXのエポック、1970年1月1日(UTC)の真夜中です。
どのような混乱を引き起こす可能性があり、しかし、であるtoString()
その値を表す文字列を生成するとき、それはJVMのデフォルトのタイムゾーンを適用すると、方法。
あなたは、UTCを懸念しているとして、私はちょうど協定世界時(UTC)が実際にあるものにあなたの注意を持ってみましょう:それは時間の標準(およびないタイムゾーン)、それは地球の回転と組み合わせた高精度な原子時計によって決定されます。
UTC時刻規格は1972年まで数回調整したうるう秒が少ない正確な原子時計よりも、完全ではない、と地球の回転に合わせてUTCを維持するために導入されました。地球の回転が減速しているとおり、すべての今して、私たちはここにあるうるう秒を挿入する必要があります。
内部値ながらDate
目的としているが、UTCを反映するために、それが原因それらのうるう秒にこれを正確に行えない場合があります。
Javaの8日付と時刻のための新しいAPI
にもかかわらず、Date
スーツのニーズ、それはUTCに来るとき、あなたはすべき避けることを。それはだレガシークラスになりました。
Javaの8は、導入された日付、時刻、インスタントや期間のための新しいAPI ISOカレンダーシステムに基づいています。最も近い同等Date
IS Instant
タイムスタンプを表し、UTCでタイムライン上の瞬間。
UTCでの現在の瞬間をキャプチャするには、次のように使用することができます。
Instant.now(); // Capture the current moment in UTC
そして、あなたは、このような値を表す文字列を取得するには、以下を使用することができます。
Instant.now().toString(); // 2019-05-17T12:50:40.474Z
この文字列はに従って書式設定されたISO 8601、Z
与えられた時間はUTCであることを示しています。
JJWTとの相互運用性
JJWT、との相互運用性のためにサポートしていないjava.time
、まだ種類を、あなたはのインスタンスを作成することができますDate
からをInstant
。
Date.from(Instant.now()); // Convert from modern class to legacy class
そして、ここであなたはトークンを発行し、検証する方法を示してテストがあります:
@Test
public void shouldMatchIssuedAtAndExpiration() {
Key key = Keys.secretKeyFor(SignatureAlgorithm.HS256);
Instant issuedAt = Instant.now().truncatedTo(ChronoUnit.SECONDS);
Instant expiration = issuedAt.plus(3, ChronoUnit.MINUTES);
log.info("Issued at: {}", issuedAt);
log.info("Expires at: {}", expiration);
String jws = Jwts.builder()
.setIssuedAt(Date.from(issuedAt))
.setExpiration(Date.from(expiration))
.signWith(key)
.compact();
Claims claims = Jwts.parser()
.setSigningKey(key)
.parseClaimsJws(jws)
.getBody();
assertThat(claims.getIssuedAt().toInstant(), is(issuedAt));
assertThat(claims.getExpiration().toInstant(), is(expiration));
}
上記の例では、私はに記載されている依存関係を持つJJWT 0.10.5を使用しました文書。あなたが必要な場合は、上記のコードは次のように書かれたimport
文:
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import java.security.Key;
import java.time.Instant;
import java.time.ZoneOffset;
import java.time.temporal.ChronoUnit;
import java.util.Date;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;