如何延长java json网络令牌的到期时间?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/29744385/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 08:32:28  来源:igfitidea点击:

How to extend expiration time java json web token?

javatokenjwt

提问by vanduc1102

I try to create Json Web Token in Java with jjwt library

我尝试使用jjwt 库在 Java 中创建 Json Web Token

But I have problem when I try to extend the expiration time.

但是当我尝试延长到期时间时遇到问题。

I try it by the code below.

我用下面的代码试试。

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();
    }
}

The result is :

结果是:

compact : eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJKb2UiLCJleHAiOjE0Mjk2NjU1MjB9.oMY2mDHvNoMZqBfic41LbiKvAyi93wIfu_WgIADb9Wc
unpackage 0 : Joe
unpackage 1 : Joe
exception : JWT expired at 2015-04-22T08:18:40+0700. Current time: 2015-04-22T08:18:42+0700

So it mean, the unpackage2cant run, Because it was expiration.

所以这意味着,unpackage2无法运行,因为它已过期。

I trying to extend the expiration time.

我试图延长到期时间。

Because I apply the code on web application.

因为我在 Web 应用程序上应用了代码。

If user still connect with my application, He should not get token timeout.

如果用户仍然与我的应用程序连接,他不应该得到令牌超时。

I have found another questionlike mine.

我发现了另一个像我一样的问题

采纳答案by Les Hazlewood

The problem is with the parsing code:

问题在于解析代码:

Jwts.parser().setSigningKey(key).parseClaimsJws(compact).getBody().setExpiration(expirationTime1).getSubject();

In this line, you're modifying the JWT that is returned by the parser. In other words, the above is equivalent to this:

在这一行中,您正在修改解析器返回的 JWT。换句话说,上面的等价于:

Jws<Claims> jws = Jwts.parser().setSigningKey(key).parseClaimsJws(compact);
jws.getBody().setExpiration(expirationTime1).getSubject();

Notice how this code modifies the JWT returned by the parser? It does not - and cannot - modify the JWT represented by the original compactString.

请注意此代码如何修改解析器返回的 JWT?它不会——也不能——修改由原始compact字符串表示的 JWT 。

Your next line of code after that tries to parse the original (unmodified) compactString:

之后的下一行代码尝试解析原始(未修改)compact字符串:

// check if the extend expiration work.
Thread.sleep(3000);            
System.out.println("unpackage 2 : " + Jwts.parser().setSigningKey(key).parseClaimsJws(compact).getBody().getSubject());

But we know this won't work because changing the state of the JWT returned by the parser does not have any effect on the original compactString.

但是我们知道这是行不通的,因为更改解析器返回的 JWT 的状态不会对原始compact字符串产生任何影响。

If your user presents a JWT to your web application and you want to 'extend the life' of the token so it won't expire, you mustgenerate a new JWT and send that JWT back to the user. The user should send the new JWT back on future requests. You keep repeating this process for as long as you want to allow the user to keep talking to your web application without having to re-login again.

如果您的用户向您的 Web 应用程序提供 JWT,并且您希望“延长令牌的生命周期”使其不会过期,您必须生成一个新的 JWT 并将该 JWT 发送回用户。用户应该在以后的请求中发回新的 JWT。只要您希望允许用户继续与您的 Web 应用程序对话而无需再次重新登录,您就一直重复此过程。

I should point out that if you don't want to worry about any of this stuff, Stormpathcan perform user and JWT token authentication between the browser and your app automatically for you - you don't have to build any of this yourself (disclosure: I'm Stormpath's CTO).

我应该指出,如果您不想担心这些事情中的任何一个,Stormpath可以自动为您在浏览器和您的应用程序之间执行用户和 JWT 令牌身份验证 - 您不必自己构建任何这些(披露:我是 Stormpath 的 CTO)。

Finally, you might be interested to know that JJWT's test suite already validates the correct behavior in numerous places for both expired and premature token use cases:

最后,您可能有兴趣知道 JJWT 的测试套件已经在许多地方验证了过期和过早令牌用例的正确行为:

But, you don't have to take my word for it :) Here is your code, modified so that your expiration modifications function as described:

但是,您不必相信我的话:) 这是您的代码,经过修改,以便您的到期修改功能如所述:

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();
    }
}
}

Notice that a 2nd newJWT (compact2) needed to be generated to reflect the new/latest expiration time. You cannot modify a parsed JWT and expect the changes to apply to the original compact value.

请注意,需要生成第二个JWT ( compact2) 以反映新的/最新的到期时间。您不能修改已解析的 JWT 并期望更改应用于原始紧凑值。

In summary, use Jwts.parser()when you need to parse a JWT string to get a nice Java object representation of the JWT. Use Jwts.builder()when you need to create or modify a JWT to produce a new compact String representation.

总之,Jwts.parser()当您需要解析 JWT 字符串以获得 JWT 的良好 Java 对象表示时使用。使用Jwts.builder()时您需要创建或修改JWT产生一个新的紧凑型字符串表示。

I hope that helps!

我希望这有帮助!