“前端计时有坑,考虑安全要靠服务端处理”

95 阅读1分钟
之前有遇到计时的场景,刚开始用前端计时,发现会有坑,然后配合redis处理,才解决了问题,比如考试页面的计时:

**考试剩余时间计时**

image.png

用前端做计时器,当页面退出时,会重新计时,所以改用redis,存储第一次进入考试的时间,每一次重新进入考试,接口返回当前和第一次进入考试的时间差。
考试剩余时间 = 后台配置的考试时长 - (当前系统的时间 - 第一次进入考试的时间)。
//参加考试时,存储当前用户进入考试的时间
long currentTime = System.currentTimeMillis();
Long userExamStartTime = redisService.getCacheObject("examStartTime:" + examId + "_" + user.getId());
if(userExamStartTime == null){
    redisService.setCacheObject("examStartTime:" + examId + "_" + user.getId(),currentTime);
    redisService.expire("examStartTime:" + examId  + "_" + user.getId(),examinationInfo.getExamTime(), TimeUnit.MINUTES);
}


//获取考试剩余时间
if(redisService.getCacheObject"examStartTime:" + examId + "_" + user.getId()) != null){
    map.put("remainingTime",getRemainingTime(examinationId,examinationInfo.getExamTime(),user.getId()));
}else {
    map.put("remainingTime",0);
}

/**
 * 获取用户剩余考试时间
 */
public long getRemainingTime(String examId,long examTime,long userId)
{
    Long userStartTime = redisService.getCacheObject("examStartTime:" + examId + "_" + userId);
    if(userStartTime != null){
        long currentTime = System.currentTimeMillis();
        long elapsedTime = currentTime - userStartTime;
        //时间戳为毫秒
        long remainingTime = examTime * 60 * 1000 - elapsedTime;
        // 返回剩余时间,确保为非负数
        return Math.max(remainingTime, 0);
    }
    return 0;
}
搭配redis计时,就算关闭页面,剩余时间也会变化,更加的安全。