背景:一个用户账号,多个设备上同时在线?可以同时操作?数据库: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调用该接口,调用成功
最后,解决问题,又可以花时间逛博(摸)客(鱼)学习了。
我是小白,喜欢记录日志的小白,欢迎大佬指点