jwt用户登录 实现用户同时在线数量限制

通常系统都会限制同一个账号的登录人数,多人登录要么限制后者登录,要么踢出前者,今天讲的是踢出前者。

JWT(token)存储在Redis中,类似 JSessionId-Session的关系,用户登录后每次请求在Header中携带jwt

比较时间戳

维护一个 username: jwtToken 这样的一个 key-value 在Reids中

拦截器逻辑

package com.gitee.taven.filter;

import com.gitee.taven.utils.JWTUtil;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RBucket;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 比较时间戳
 */
public class CompareKickOutFilter extends KickOutFilter {
    @Override
    public boolean isAccessAllowed(HttpServletRequest request, HttpServletResponse response) {
        String token = request.getHeader("Authorization");
        String username = JWTUtil.getUsername(token);
        String userKey = PREFIX + username;

        RBucket<String> bucket = redissonClient.getBucket(userKey);
        String redisToken = bucket.get();

        if (token.equals(redisToken)) {
            return true;

        } else if (StringUtils.isBlank(redisToken)) {
            bucket.set(token);

        } else {
            Long redisTokenUnixTime = JWTUtil.getClaim(redisToken, "createTime").asLong();
            Long tokenUnixTime = JWTUtil.getClaim(token, "createTime").asLong();

            // token > redisToken 则覆盖
            if (tokenUnixTime.compareTo(redisTokenUnixTime) > 0) {
                bucket.set(token);

            } else {
                // 注销当前token
                userService.logout(token);
                sendJsonResponse(response, 4001, "您的账号已在其他设备登录");
                return false;

            }

        }

        return true;

    }
}

用户登录成功 生成token给到用户 同时存储到redis中(key值为用户名(标识)) 

用户再次访问系统请求参数中带有token信息 后台拦截进行比对

如果token匹配成功 就放行 匹配不成功 说明两个token不一致 开始比对对应的时间戳 后者时间戳 大于前者 就把当前token覆盖(如果旧的token请求再次进来 期时间戳就晚于当前redis中的token时间(token已经更新)判断其为被踢出的用户提示重新登录)

猜你喜欢

转载自blog.csdn.net/u012565281/article/details/110864387
今日推荐