JWT认证,取得过期token的用户名

3,833 阅读1分钟

前言

项目前后端分离,请求认证使用的是JWT无状态认证。最近遇到一个问题,认证token需要从token中获取用户名,但是这个token有可能是过期的。一般取得用户名用的是下面的代码。

private Claims getClaimsFromToken(String token) {
        return Jwts.parser()
                .setSigningKey(SECRET)
                .parseClaimsJws(token)
                .getBody();
}

如果token没有过期,则可以通过Claims.getSubject()获得用户名。但是token过期,则会抛出ExpiredJwtException异常,导致无法获取用户名。

解决方法

查看ExpiredJwtException异常,会发现它的父类ClaimJwtException封装了Claims类成员。所以只要调用getClaims()方法就可以取得Claim对象,进而取得用户名。

public abstract class ClaimJwtException extends JwtException {
    public static final String INCORRECT_EXPECTED_CLAIM_MESSAGE_TEMPLATE = "Expected %s claim to be: %s, but was: %s.";
    public static final String MISSING_EXPECTED_CLAIM_MESSAGE_TEMPLATE = "Expected %s claim to be: %s, but was not present in the JWT claims.";
    private final Header header;
    private final Claims claims;

    protected ClaimJwtException(Header header, Claims claims, String message) {
        super(message);
        this.header = header;
        this.claims = claims;
    }

    protected ClaimJwtException(Header header, Claims claims, String message, Throwable cause) {
        super(message, cause);
        this.header = header;
        this.claims = claims;
    }

    public Claims getClaims() {
        return this.claims;
    }

    public Header getHeader() {
        return this.header;
    }
}

取得用户名的代码如下。


/**
 * 从token中获取用户名
 */
public String getUsernameFromToken(String token) {
    try {
        return getClaimsFromToken(token).getSubject();
    } catch (ExpiredJwtException e) {
        // 过期则从ExpiredJwtException中取username
        return e.getClaims().getSubject();
    }
}