16

如果我们尝试解析expired JWT,会导致 expired 异常。

即使 JWT 已过期,有没有办法读取声明。

下面用于在java中解析JWT:

Jwts.parser().setSigningKey(secret.getBytes()).parseClaimsJws(token).getBody();

4

6 回答 6

42

有更好的方法来做到这一点。如果您看到 JWT 异常处理程序对象,例如 ExpiredJwtException,期望对象本身包含以下内容:- 标头、声明和消息

因此可以通过此对象轻松提取声明,即e.getClaims().getId()其中 e 是 ExpiredJwtException 对象。

ExpiredJwtException 构造如下:-

public ExpiredJwtException(Header header, Claims claims, String message) {
        super(header, claims, message);
}

例子:-

    try{
        // executable code
   }catch(ExpiredJwtException e){
        System.out.println("token expired for id : " + e.getClaims().getId());
    }
于 2017-04-24T06:07:54.977 回答
15

JWT 对象是 Base64URL 编码的。这意味着您始终可以通过手动 Base64URL 解码来读取标头和有效负载。在这种情况下,您将简单地忽略exp属性。

例如,您可以这样做(我使用的是 Java8 内置Base64类,但您可以使用任何外部库,例如Apache Commons Codec):

Base64.Decoder decoder = Base64.getUrlDecoder();
String src = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImV4cCI6IjEzMDA4MTkzODAifQ.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.2GpoV9q_uguSg0Ku6peI5aZ2qBxO5qOA42zaS25gq_c";
String[] parts = src.split("\\."); // Splitting header, payload and signature
System.out.println("Headers: "+new String(decoder.decode(parts[0]))); // Header
System.out.println("Payload: "+new String(decoder.decode(parts[1]))); // Payload

输出是:

Headers: {"alg":"HS256","typ":"JWT","exp":"1300819380"}
Payload: {"sub":"1234567890","name":"John Doe","admin":true}

另请注意,该exp属性设置为1300819380,对应于16 january 2016

于 2016-03-04T08:43:45.977 回答
6

这可能是旧的,但对于任何面临这个问题的人来说,javaio.jsonwebtoken ExpiredJwtException已经得到了它的声明,你可以通过调用来获得它e.getClaims()

于 2019-11-04T15:12:46.113 回答
0

如果有人进来寻找 jose4j 库,那么以下工作:

invalidJwtException.getJwtContext().getJwtClaims()
于 2020-11-11T12:28:05.223 回答
0

只需在调用 ValidateToken 之前将 TokenValidationParameters 的 ValidateLifetime 属性设置为 false。

TokenValidationParameters tokenValidationParameters = new TokenValidationParameters();
tokenValidationParameters.ValidateLifetime = false;

JwtSecurityTokenHandler jwtSecurityTokenHandler = new JwtSecurityTokenHandler();
ClaimsPrincipal principal = jwtSecurityTokenHandler.ValidateToken(token, tokenValidationParameters, out SecurityToken validatedToken);

然后你可以阅读这样的声明:

string name = principal.Claims.FirstOrDefault(e => e.Type.Equals(ClaimTypes.Name)).Value;
string email = principal.Claims.FirstOrDefault(e => e.Type.Equals(ClaimTypes.Email)).Value;
于 2021-01-21T19:18:03.580 回答
0

如果你使用io.jsonwebtoken你试试我的功能:

public Claims getClaimsFromToken(String token) {
        try {
            // Get Claims from valid token
            return Jwts.parser()
                    .setSigningKey(SECRET)
                    .parseClaimsJws(token)
                    .getBody();
            
        } catch (ExpiredJwtException e) {
            // Get Claims from expired token
            return e.getClaims();
        } 
    }
于 2021-08-16T17:41:25.673 回答