记录一次Calendar使用不当的BUG

121 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 12 天,点击查看活动详情

自己去年做了一个个人网站 workp.vip.cpolar.cn 年前回家的时候发布了最新版本,昨天登录我的网站的时候发现怎么都登录失败,一直报错:token登录失败。最后通过服务器日志定位了问题,

image.png

原来是我登录时产生的token过期了。

下面是我的JwtUtil工具类

public final class JwtUtil{
    private final static Calendar INSTANCE = Calendar.getInstance();

    static {
        // 默认7天登录有效期
        INSTANCE.add(Calendar.DATE, 7);
    }
    
    /**
     * 根据payload(也就是clamis)获取token字符串
     *
     * @param claims payload的数据集合
     * @return token
     */
    public static String getToken(Map<String, Object> claims) throws UnsupportedEncodingException {
        return getToken(claims, INSTANCE.getTime());
    }
}

JwtUtil中我把Calendar定义成了一个静态的成员变量,这样就导致INSTANCE实例永远是启动时刻的时间。而我是去年启动的项目,之前开发的时候经常两三天会重启一次项目调整Bug。我的token是7天过期,所以之前我没有发现这个Bug。

而过年回来之后,我的登录Token早已经过期了,当我重新登录的时候,新的Token还是基于去年时间段(一月份)生成的,那么过期时间就是去年启动时间+7天(还是一月),所以无论怎样都会登录失败,报错token过期。

解决方案

我们通常都是通过Calendar类来计算日期,虽然它的API有很多不完善的地方,但是使用它计算简单的日期还是可以的。最终解决方案就是把静态实例定义成方法的局部变量。每次生成token时都获取最新时间。

public static String getToken(Map<String, Object> claims) throws UnsupportedEncodingException {
    return getToken(claims, getExpireDate());
}

public static Date getExpireDate(){
    Calendar instance = Calendar.getInstance();
    instance.add(Calendar.DATE, 7);
    return instance.getTime();
}

结语

看来static使用不当,很容易引发不知情的Bug呀。Bug仍未消除完毕,同志们仍需努力!加油~