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

时间:2015-04-20 09:45:22

标签: java token jwt

我尝试使用jjwt library

在Java中创建Json Web Token

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

我通过以下代码尝试。

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

结果是:

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

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

我试图延长到期时间。

因为我在网络应用程序上应用代码。

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

我发现another question和我一样。

1 个答案:

答案 0 :(得分:10)

问题在于解析代码:

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,并且您希望延长生命周期。因为它不会过期,你必须生成一个新的JWT并将该JWT发送回用户。用户应该在将来的请求中重新发送新的JWT。只要您希望允许用户继续与您的Web应用程序通信而不必再次重新登录,您就会不断重复此过程。

我应该指出,如果您不想担心这些问题,Stormpath可以自动为您执行浏览器和应用之间的用户和JWT令牌身份验证 - 您不会我必须自己构建这些(披露:我是Stormpath的首席技术官)。

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

但是,你不必接受我的话:)这是你的代码,修改后你的到期修改功能如下所述:

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

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

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

我希望有所帮助!