Redis 实现多端登录踢人下线功能

需求:用户在客户端A登录,然后又在客户端B登录会将挤下客户端A的登录,也就是不允许用户在不同的客户端登录。

private void redisSaveLoginToken(String userIdMD5, String newToken) {
    String redisKey = RedisConstant.REDIS_USER_PREFIX + userIdMD5;
    BoundValueOperations<String, String> operations = stringRedisTemplate.boundValueOps(redisKey);

    // 获取旧token
    String oldToken = operations.get();

    // 设置新token
    if (StringUtils.isNotBlank(newToken)) {
        operations.set(newToken, RedisConstant.REDIS_TOKEN_TTL, TimeUnit.MINUTES);
    }

    // 传递旧token给redisSaveUserInfo方法
    redisSaveUserInfo(newToken, user, remoteAddr, oldToken);
}

private void redisSaveUserInfo(String newToken, User user, String remoteAddr, String oldToken) {
    String redisKey = RedisConstant.REDIS_TOKEN_PREFIX + newToken;
    UserDto userDto = new UserDto();
    BeanUtils.copyProperties(user, userDto);
    userDto.setRemoteAddr(remoteAddr);

    String userJSON = JacksonUtil.writeValueAsString(userDto);
    log.info("[redisSaveUserInfo] userJSON:{}", userJSON);

    try {
        stringRedisTemplate.opsForValue().set(redisKey, userJSON, RedisConstant.REDIS_TOKEN_TTL, TimeUnit.MINUTES);
    } catch (Exception e) {
        log.error("[Redis-addOps]" + e.getMessage());
    }

    // 根据旧token删除Redis旧客户端登录的用户信息(旧token作废),oldToken==null 表示第一次登录
    if (StringUtils.isNotBlank(oldToken)) {
        log.info("oldToken:{}", oldToken);
        String deleteKey = RedisConstant.REDIS_TOKEN_PREFIX + oldToken;

        try {
            stringRedisTemplate.delete(deleteKey);
        } catch (Exception e) {
            log.error("[Redis-delOps]" + e.getMessage());
        }
    }
}

后续补充:上面的方案将用户信息存在Redis 相对占用资源,下面的方案是结合JWT 来做,token 存在客户端,JWT 的非对称加密也会更加安全 (推荐)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值