目的:每个用户只允许一个session可用,在redis中也只能有一条session记录
为演示直接在Controller
层进行控制(我也不是很清楚应该在哪里进行控制,哈哈哈)
思路:shiro
认证通过之后向session
中保存当前登录的账号(唯一识别),获取redis
中存的所有session
,依据上次登录向session保存的信息找到上一次存的session
,先删除redis
中的session
,在设置session
失效。
缺点:用户量大的时候效率太低。
@PostMapping("/login")
public Object login(String phone,String password) {
System.out.println(password+phone);
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken upToken = new UsernamePasswordToken(phone, password);
try {
subject.login(upToken);
// shiro认证通过之后 才进行session的替换
if (subject.isAuthenticated()) {
// 获取所有的session
Collection<Session> activeSessions = sessionDAO.getActiveSessions();
if(activeSessions.size() > 0) {
activeSessions.forEach(session -> {
// 找到当前phone的session(上一次存的session)
if (phone.equals(session.getAttribute("phoneKey")) {
// 先在redis 中删除
sessionRedisTemplate.delete(AppConstants.SHIRO_SESSION_REDIS_PREFIX + session.getId());
// 在设置session失效,否则先失效就获取不到id了
session.setTimeout(0);
}
});
}
}
/*向session中保存当前登录的手机号,以便检测是否登录过*/
subject.getSession().setAttribute("phoneKey", phone);
} catch (UnknownAccountException | IncorrectCredentialsException e) {
return ResultEntity.error(ResultStatus.USERNAME_OR_PASSWORD_ERROR);
}
return ResultEntity.ok();
}