如何延长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
How to extend expiration time java json web token?
提问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 compact
String.
请注意此代码如何修改解析器返回的 JWT?它不会——也不能——修改由原始compact
字符串表示的 JWT 。
Your next line of code after that tries to parse the original (unmodified) compact
String:
之后的下一行代码尝试解析原始(未修改)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 compact
String.
但是我们知道这是行不通的,因为更改解析器返回的 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 的测试套件已经在许多地方验证了过期和过早令牌用例的正确行为:
- https://github.com/jwtk/jjwt/blob/0.4/src/test/groovy/io/jsonwebtoken/JwtParserTest.groovy#L163-L189
- https://github.com/jwtk/jjwt/blob/0.4/src/test/groovy/io/jsonwebtoken/JwtParserTest.groovy#L307-L335
- https://github.com/jwtk/jjwt/blob/0.4/src/test/groovy/io/jsonwebtoken/JwtParserTest.groovy#L421-L454
- https://github.com/jwtk/jjwt/blob/0.4/src/test/groovy/io/jsonwebtoken/JwtParserTest.groovy#L163-L189
- https://github.com/jwtk/jjwt/blob/0.4/src/test/groovy/io/jsonwebtoken/JwtParserTest.groovy#L307-L335
- https://github.com/jwtk/jjwt/blob/0.4/src/test/groovy/io/jsonwebtoken/JwtParserTest.groovy#L421-L454
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!
我希望这有帮助!