Java 单点登录--只能在一台设备上登录

背景:一个用户账号,多个设备上同时在线?可以同时操作?数据库:6 , 经理:我裂开     我:删库跑路

  为了避免该情况,要求系统必须具备限制用户只能在一台设备上登录,在别的设备上登录之后,当前设备要下线,如何判断是否重新登陆,恰好可以用登录时生成的token来验证,在别的设备上登录之后,接口请求里的token与当前token不一致,直接下线跳转到登陆页面,再使用炉火纯青的Redis数据库存储token,简单的单点登录功能完成了,什么?low?能跑就行!

1.登录模块代码实现
@ApiOperation(value = "登录")
    @PostMapping("/login")
    public BaseResult<Map> login(@RequestBody UserDTO userDTO) {

        String number = userDTO.getNumber();
        String code = userDTO.getCode();
        //查询用户信息(用户姓名,用户ID)
        User user = userService.verifyIdentity(number);
        userDTO.setUserId(user.getUserId());
        //jwt工具生成token
        JwtUserBO jwtUserBO = new JwtUserBO();
        jwtUserBO.setUserId(user.getUserId());
        jwtUserBO.setUserName(user.getUserName());
        String token = jwtUtil.signTokens(jwtUserBO);
        //token存放到redis中并设置过期时间,这里是8小时
        redisUtil.set("econ-token:"+token, token, 28800L);
        Map<String, Object> userInfo = new HashMap<>();
        userInfo.put("token", token);
        userInfo.put("user", userDTO);
        log.info("登录信息:{}", userInfo);
        return BaseResult.success(userInfo);

    }
2.@AuthValid接口鉴权代码实现(AOP操作,在方法执行之前执行鉴权代码)
 @Around(value = "anyMethod()")
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
        String token = jwtUtil.getToken();
        String key = String.valueOf(jwtUtil.getUserId());
        if (!StringUtils.hasText(token)) {
            log.warn("no login!");
            return BaseResult.fail("4003", MessageUtils.get("common.no_logged_in"));
        }
        //单点登录
        if(redisUtil.hasKey(key)){
            if(!Objects.equals(redisUtil.get(key), token)){
                return BaseResult.fail("4000", MessageUtils.get("common.login.information.invalid"));
            }
        }
        //token是否过期
        if (jwtUtil.isTokenExpired(token)) {
            return BaseResult.fail("4000", MessageUtils.get("epro.token.invalid"));
        }

      }
        //鉴权通过,执行后续方法
        return pjp.proceed();
    }
3.找一个需要鉴权的接口(获取版本号),用apiPost测试下
    @AuthValid
    @ApiOperation("获取android/apple版本号")
    @GetMapping("/info")
    public Result<Object> getVersion() {
        String datasourceId = jwtUtil.getProjectKey();
        return ResponseUtil.getServiceResponseResult(appVersionService.getEconVersion(datasourceId));
    }
(1)首先获取验证码登录,登陆成功

(2)将登陆生成的token放到请求头,请求接口成功

(3)再次调用登录接口,模拟在别的设备上登录

(4)token已刷新,获取版本号接口仍然使用之前的token模拟在原设备请求接口,请求失败,前端可以跳转到登陆页面

打断点看下鉴权处理情况,校验未通过

(5)使用新的token调用该接口,调用成功

最后,解决问题,又可以花时间逛博(摸)客(鱼)学习了。

我是小白,喜欢记录日志的小白,欢迎大佬指点

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

在比萨斜塔吃披萨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值