Java with jjwt library でJson Webトークンを作成しようとしています
しかし、有効期限を延長しようとすると問題があります。
以下のコードで試してみます。
public class Main {
public static void main(String args[]) {
byte[] key = new byte[64];
new SecureRandom().nextBytes(key);
Date date = new Date();
long t = date.getTime();
Date expirationTime = new Date(t + 5000l); // set 5 seconds
String compact = Jwts.builder().setSubject("Joe").setExpiration(expirationTime).signWith(SignatureAlgorithm.HS256, key).compact();
System.out.println("compact : " + compact);
try {
String unpack = Jwts.parser().setSigningKey(key).parseClaimsJws(compact).getBody().getSubject();
System.out.println("unpackage 0 : " + unpack);
// check if the expiration work.
Thread.sleep(3000);
System.out.println("unpackage 1 : " + Jwts.parser().setSigningKey(key).parseClaimsJws(compact).getBody().getSubject());
//extend the expration time.
Date date1 = new Date();
long t1 = date1.getTime();
Date expirationTime1 = new Date(t1 + 5000l); //prolongation 5 seconds
Jwts.parser().setSigningKey(key).parseClaimsJws(compact).getBody().setExpiration(expirationTime1).getSubject();
// check if the extend expiration work.
Thread.sleep(3000);
System.out.println("unpackage 2 : " + Jwts.parser().setSigningKey(key).parseClaimsJws(compact).getBody().getSubject());
} catch (InterruptedException | ExpiredJwtException ex) {
System.out.println("exception : " + ex.getMessage());
Thread.currentThread().interrupt();
}
}
結果は:
コンパクト:eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJKb2UiLCJleHAiOjE0Mjk2NjU1MjB9.oMY2mDHvNoMZqBfic41LbiKvAyi93wIfu_WgIADb9W 0700。現在の時刻:2015-04-22T08:18:42 + 0700
つまり、unpackage2は、期限切れのため実行できません。
有効期限を延長しようとしています。
コードをWebアプリケーションに適用するためです。
ユーザーがまだアプリケーションに接続している場合、トークンのタイムアウトは発生しません。
私は 別の質問 を見つけました。
問題は解析コードにあります:
_Jwts.parser().setSigningKey(key).parseClaimsJws(compact).getBody().setExpiration(expirationTime1).getSubject();
_
この行では、パーサーによって返されるJWTを変更しています。つまり、上記はこれと同等です。
_Jws<Claims> jws = Jwts.parser().setSigningKey(key).parseClaimsJws(compact);
jws.getBody().setExpiration(expirationTime1).getSubject();
_
このコードがパーサーによって返されたJWTをどのように変更するかに注意してください。元のcompact
文字列で表されるJWTを変更することはできず、変更することもできません。
その後の次のコード行は、元の(変更されていない)compact
文字列を解析しようとします。
_// check if the extend expiration work.
Thread.sleep(3000);
System.out.println("unpackage 2 : " + Jwts.parser().setSigningKey(key).parseClaimsJws(compact).getBody().getSubject());
_
ただし、パーサーによって返されたJWTの状態を変更しても、元のcompact
文字列には影響がないため、これは機能しません。
ユーザーがJWTをWebアプリケーションに提示し、トークンの「有効期間を延長」して有効期限が切れないようにしたい場合は、mustを生成する必要があります新しいJWTを作成し、そのJWTをユーザーに送り返します。ユーザーは、今後のリクエストで新しいJWTを送り返す必要があります。ユーザーが再ログインせずにWebアプリケーションと対話できるようにしたい限り、このプロセスを繰り返し続けます。
このことについて心配したくない場合は、 Stormpath がブラウザとアプリの間でユーザーとJWTトークンの認証を自動的に実行できることを指摘しておく必要はありません。これを自分で構築します(開示:私はStormpathのCTOです)。
最後に、JJWTのテストスイートが、期限切れのトークンと時期尚早のトークンの両方のユースケースの多くの場所で正しい動作をすでに検証していることを知りたいと思うかもしれません。
しかし、あなたは私のWordをそれのために取る必要はありません:)以下は、記述されているように有効期限の変更が機能するように変更されたコードです:
_public class Main {
public static void main(String args[]) {
byte[] key = new byte[64];
new SecureRandom().nextBytes(key);
Date date = new Date();
long t = date.getTime();
Date expirationTime = new Date(t + 5000l); // set 5 seconds
String compact = Jwts.builder().setSubject("Joe").setExpiration(expirationTime).signWith(SignatureAlgorithm.HS256, key).compact();
System.out.println("compact : " + compact);
try {
String unpack = Jwts.parser().setSigningKey(key).parseClaimsJws(compact).getBody().getSubject();
System.out.println("unpackage 0 : " + unpack);
// check if the expiration work.
Thread.sleep(3000);
System.out.println("unpackage 1 : " + Jwts.parser().setSigningKey(key).parseClaimsJws(compact).getBody().getSubject());
//Create a *new* token that reflects a longer extended expiration time.
Date date1 = new Date();
long t1 = date1.getTime();
Date expirationTime1 = new Date(t1 + 5000l); //prolongation 5 seconds
String compact2 = Jwts.builder().setSubject("Joe").setExpiration(expirationTime1).signWith(SignatureAlgorithm.HS256, key).compact();
// check if the extend expiration work.
Thread.sleep(3000);
System.out.println("unpackage 2 : " + Jwts.parser().setSigningKey(key).parseClaimsJws(compact2).getBody().getSubject());
Thread.sleep(1000);
} catch (InterruptedException | ExpiredJwtException ex) {
System.out.println("exception : " + ex.getMessage());
Thread.currentThread().interrupt();
}
}
}
_
新しい/最新の有効期限を反映するために、2番目のnewJWT(_compact2
_)を生成する必要があることに注意してください。解析済みのJWTを変更して、変更が元のコンパクト値に適用されることを期待することはできません。
要約すると、JWTの文字列を解析してJWTのNice Javaオブジェクト表現を取得する必要がある場合はJwts.parser()
を使用します。必要な場合はJwts.builder()
を使用してくださいJWTを作成または変更して、新しいコンパクトな文字列表現を生成します。
お役に立てば幸いです。