解析时,JWT令牌始终被接收为已过期 [英] JWT Token is always received as expired while parsing
问题描述
我在一个应用程序中使用JWT Authentictaion以及Spring Boot/Security,这是我第一次使用JWT.
I am using JWT Authentictaion in one of my application along with Spring Boot/Security and its my first take on JWT.
以下是我的设置和获取身份验证方法:
Following are my set and get authentication methods:
static void addAuthentication(HttpServletResponse res, JWTPayload payload) {
// all authentication related data like authorities and permissions can be
// embed to the token in a map using setClaims()
Map<String, Object> claims = new HashMap<String, Object>();
claims.put("roles", payload.getRoles());
claims.put("permissions", payload.getPermissions());
String JWT = Jwts.builder()
.setSubject(payload.getUsername())
.setClaims(claims)
.setExpiration(new Date(System.currentTimeMillis() + EXPIRATIONTIME))
.signWith(SignatureAlgorithm.HS512, SECRET_KEY)
.compact();
res.addHeader(HEADER_STRING, TOKEN_PREFIX + " " + JWT);
}
/**
* this method retrives the token from the header and validates it.
* this method is called from the JWTAuthentication filter which is
* used against all the incoming calls except the login.
* @param request
* @return
*/
static Authentication getAuthentication(HttpServletRequest request) {
String token = request.getHeader(HEADER_STRING);
if (token != null) {
// parse the token.
String user = Jwts.parser()
.setSigningKey(SECRET_KEY)
.parseClaimsJws(token.replace(TOKEN_PREFIX, ""))
.getBody()
.getSubject();
return user != null ?
new UsernamePasswordAuthenticationToken(user, null, emptyList()) :
null;
}
return null;
}
生成JWT并在标头中接收它就好了.但是,如果在后续的API调用中使用,则会收到以下错误.
The JWT is generated and received in headers just fine. However, if used in subsequent API call, I receive following error.
io.jsonwebtoken.ExpiredJwtException: JWT expired at 2018-10-31T16:06:05Z. Current time: 2018-10-31T16:06:08Z, a difference of 3421 milliseconds. Allowed clock skew: 0 milliseconds.
该异常表示允许的时钟偏移为0毫秒.在我上面的代码中,EXPIRATIONTIME
设置为30000(我相信这是在几秒钟内设置的).我也尝试增加此值,但仍然出现错误.
The exception says allowed clock skew is 0 milliseconds. In my above code EXPIRATIONTIME
is set to 30000 (I believe this is set in seconds). I have tried increasing this value too but I still get the error.
请提出我在做什么错了吗?
Please suggest what am I doing wrong ?
推荐答案
不确定您是否已经找到答案,但是有些人可能会从中受益.最初我遇到相同的问题,我认为这是JWT的问题.但是,当我调试代码时,才知道我犯了一个愚蠢的错误,并且过期日期是过去设置的.
Not sure if you have already got an answer, but someone might benefit from this some time. I had the same problem initially and I thought it was an issue with JWT. But, when I debugged my code, got to know that I was doing a silly mistake and the expiration date was set in the past.
因此,为了测试这一点,我创建了一个示例程序,您可以独立执行该程序.选中此复选框并相应地修改您的代码.希望这会有所帮助.
So, for testing this I have created a sample program that you can execute standalone. Check this and modify your code accordingly. Hope this helps.
import java.security.Key;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.UUID;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
public class TestJWTToken {
private static final String API_KEY = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
public static void main(String... args) {
String jwt = createJWT();
System.out.println("JWT: " + jwt);
parseJWT(jwt);
}
private static String createJWT() {
Calendar cal = Calendar.getInstance(Locale.UK);
Calendar cal1 = Calendar.getInstance(Locale.UK);
cal1.setTime(cal.getTime());
cal1.add(Calendar.SECOND, 300);
byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(API_KEY);
Key signingKey = new SecretKeySpec(apiKeySecretBytes, SignatureAlgorithm.HS256.getJcaName());
Map<String, Object> map = new HashMap<>();
map.put("alg", "HS256");
map.put("typ", "JWT");
String someId = UUID.randomUUID().toString();
return Jwts.builder().setHeader(map).setIssuer("service_provider").setSubject("consumer_provider_connectivity_token")
.claim("some_id", someId).setIssuedAt(cal.getTime()).setExpiration(cal1.getTime())
.signWith(SignatureAlgorithm.HS256, signingKey).compact();
}
private static void parseJWT(String jwt) {
Jws<Claims> jwsClaims = Jwts.parser().setSigningKey(DatatypeConverter.parseBase64Binary(API_KEY)).parseClaimsJws(jwt);
System.out.println("JWT decoded: " + jwsClaims);
Claims claims = jwsClaims.getBody();
System.out.println("Subject: " + claims.getSubject());
System.out.println("Issuer: " + claims.getIssuer());
System.out.println("Issued at: " + claims.getIssuedAt());
System.out.println("Expiration: " + claims.getExpiration());
System.out.println("Some_Id: " + claims.get("some_id"));
}
}
这篇关于解析时,JWT令牌始终被接收为已过期的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!