若依分离版解决单个账号多设备登录问题

若依分离版解决单个账号多设备登录问题

1.application.yml添加相关配置,用于灵活控制单个账号多设备登录的情况

#token配置
token: # 这个是若依框架本身存在的配置 
	# 是否允许并多设备登录   true:允许  false:不允许  这个是新增的配置
    singleLogin: false

2.CacheConstants类中新增常量

/**
 * 登录用户id redis key 用于实现灵活控制多设备登录
 */
public static final String LOGIN_USER_ID_KEY = "login_user_ids:";

3.TokenService类中新增相关代码(重要改动)

头部添加获取我们上面新增的配置

	// 是否允许多设备登录
    @Value("${token.singleLogin}")
    private boolean singleLogin;

在尾部添加涉及本次控制并发登录所需要的redis key组成

//userId 是 当前登录用户的主键id  注意:若依分离版默认的用户主键是Integer类型,博主实际项目后续做过调整,已改成String类型
private String getUserKey(String userId)
{
    return CacheConstants.LOGIN_USER_ID_KEY + userId;
}

refreshToken方法中做代码调整

主要原因:在这里做主要是保证后续如果由多种登录方式 手机验证码等 可以兼容(只要都调用了createToken方法去创建token令牌)

源代码:

loginUser.setLoginTime(System.currentTimeMillis());
loginUser.setExpireTime(loginUser.getLoginTime() + expireTime * MILLIS_MINUTE);
// 根据uuid将loginUser缓存
String userKey = getTokenKey(loginUser.getToken());
redisCache.setCacheObject(userKey, loginUser, expireTime, TimeUnit.MINUTES);

改造后:

//如果不允许多设备登录,则获取之前的token以及userId 判断存在,则删除
if(!singleLogin){//多设备登录限制相关代码
    String userIdKey = getUserKey(loginUser.getUserId());
    String userKey = redisCache.getCacheObject(userIdKey);
    if(StringUtils.isNotEmpty(userKey)){
        redisCache.deleteObject(userIdKey);
        redisCache.deleteObject(userKey);
    }
}
loginUser.setLoginTime(System.currentTimeMillis());
loginUser.setExpireTime(loginUser.getLoginTime() + expireTime * MILLIS_MINUTE);
// 根据uuid将loginUser缓存
String userKey = getTokenKey(loginUser.getToken());
redisCache.setCacheObject(userKey, loginUser, expireTime, TimeUnit.MINUTES);

if(!singleLogin){//多设备登录限制相关代码
    String userIdKey = getUserKey(loginUser.getUserId());
    redisCache.setCacheObject(userIdKey, userKey, expireTime, TimeUnit.MINUTES);
}

delLoginUser做代码新增,这个方法用于手动退出时 删除对应的token以及我们本次维护的redis key,也就是后续对LogoutSuccessHandlerImpl类做调整的一部分

源代码:

public void delLoginUser(String token)
{
    if (StringUtils.isNotEmpty(token))
    {
        String userKey = getTokenKey(token);
        redisCache.deleteObject(userKey);
    }
}

改造后:

public void delLoginUser(String token,String userId)
{
    if (StringUtils.isNotEmpty(token))
    {
        String userKey = getTokenKey(token);
        redisCache.deleteObject(userKey);
    }
    if (StringUtils.isNotEmpty(userId))
    {
        String userIdKey = getUserKey(userId);
        redisCache.deleteObject(userIdKey);
    }
}

新增用于强制推出方法,用于后续SysUserOnlineController类强制退出接口代码做相关调整,在前端的监控-在线用户界面做强退操作

/**
 * 强制退出
 * @param tokenId   token(uuid)
 */
public void forceLogout(String tokenId){
    String userKey = getTokenKey(tokenId);
    if(!singleLogin){//多设备登录相关控制代码
        LoginUser loginUser = redisCache.getCacheObject(userKey);
        String userId = loginUser.getUserId();
        String userIdKey = getUserKey(userId);
        redisCache.deleteObject(userIdKey);
    }
    redisCache.deleteObject(userKey);
}

4.自定义退出处理类LogoutSuccessHandlerImpl做调整

源代码:

tokenService.delLoginUser(loginUser.getToken());

改造后:

tokenService.delLoginUser(loginUser.getToken(),loginUser.getUserId());

5.在线用户监控接口类SysUserOnlineController做相关调整

头部引入TokenService类,注意引包时,引入项目的,而不是Security包的

import com.ruoyi.framework.web.service.TokenService;

@Autowired
private TokenService tokenService;

强退方法forceLogout调整

源代码:

public AjaxResult forceLogout(@PathVariable String tokenId)
{
    redisCache.deleteObject(CacheConstants.LOGIN_TOKEN_KEY + tokenId);
    return AjaxResult.success();
}

改造后:

tokenService.forceLogout(tokenId);

参考

若依项目如何实现一个账户只能一个人登录(汇总)

  • 6
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值