java实现登陆失败n次锁定账户,y分钟后自动解锁,两次失败间隔时间过大则不计次数(含redis处理)

时间:2025-03-19 16:43:57
public class LoginServiceImpl implements LoginService { private static final Logger logger = LoggerFactory.getLogger(LoginServiceImpl.class); @Autowired private LoginLogMapper loginLogMapper; @Autowired private SysUserDao sysUserDao; @Autowired private SysMenuDao sysMenuDao; @Override public LoginResponse login(String userName,String password) { if (StringUtils.isBlank(userName) || StringUtils.isBlank(password)) { recordLogininfor(userName, LoginLog.FAIL, "用户/密码为空"); throw new BizException(BizExceptionEnum.USER_NAME_PWD_NULL); } SysUserDO user = sysUserDao.getByUserName(userName); if (Objects.isNull(user)) { recordLogininfor(userName, LoginLog.FAIL, "用户不存在"); throw new BizException(BizExceptionEnum.USER_NOT_FOUND); } if (user.getDel().equals(Constant.YES)) { recordLogininfor(userName, LoginLog.FAIL, "用户被删除"); throw new BizException(BizExceptionEnum.AUTH_USER_DEL_OR_LOCKED); } if (user.getStatus().equals(UserStatus.DISABLE.getCode())) { recordLogininfor(userName, LoginLog.FAIL, "用户被锁定"); throw new BizException(BizExceptionEnum.USER_LOCKED); } //用户锁定后,时间到了解锁,时间未到抛出异常信息 if (user.getLoginStatus().equals("2")) { long errorTime = user.getLastLoginErrorTime().getTime(); long nowTime = System.currentTimeMillis(); long time = (nowTime - errorTime) / (1000 * 60); if (30 - time <= 0) { user.setLastLoginErrorTime(null); user.setLoginStatus("1"); user.setLoginErrorCount(0); sysUserDao.update(user); } else { recordLogininfor(userName, LoginLog.FAIL, "用户登陆被锁定中"); throw new BizException("当前用户登陆已锁定,请" + (30 - time) + "分钟后重试"); } } //密码错误开始 if (!user.getPassword().equalsIgnoreCase(password)) { SysUserDO userErr = sysUserDao.getByUserName(userName); //获取错误登陆 Integer loginErrorCount = userErr.getLoginErrorCount(); //获取上次登陆错误时间 Date lastLoginErrorTime = userErr.getLastLoginErrorTime(); //获取用户是否登陆锁定 锁定 1:正常,2:锁定 String loginStatus = userErr.getLoginStatus(); if (loginErrorCount == 3) { userErr.setLoginStatus("2"); sysUserDao.update(userErr); recordLogininfor(userName, LoginLog.FAIL, "用户密码错误次数达到上限,已锁定"); throw new BizException("当前用户登陆已锁定,请30分钟后重试"); } else { //如果登陆次数为0,代表还没有登陆失败记录 if (loginErrorCount == 0) { userErr.setLoginErrorCount(loginErrorCount + 1); userErr.setLastLoginErrorTime(new Date()); sysUserDao.update(userErr); recordLogininfor(userName, LoginLog.FAIL, "用户密码错误"); throw new BizException("登陆失败,可尝试登陆次数为:" + (3 - (loginErrorCount))); // } else { long timeError = userErr.getLastLoginErrorTime().getTime(); long timeNow = System.currentTimeMillis(); long time = (timeNow - timeError) / (1000 * 60); //如果两次的登陆失败的时间差大于n分钟,则不计错误次数,此处用1分钟代替 if (time >= 1) { if (loginErrorCount == 1) { userErr.setLastLoginErrorTime(new Date()); sysUserDao.update(userErr); recordLogininfor(userName, LoginLog.FAIL, "用户密码错误"); throw new BizException("登陆失败,可尝试登陆次数为:" + 3); } else { userErr.setLoginErrorCount(loginErrorCount); userErr.setLastLoginErrorTime(new Date()); sysUserDao.update(userErr); recordLogininfor(userName, LoginLog.FAIL, "用户密码错误"); throw new BizException("登陆失败,可尝试登陆次数为:" + (3 - (loginErrorCount))); } } else { userErr.setLoginErrorCount(loginErrorCount + 1); userErr.setLastLoginErrorTime(new Date()); sysUserDao.update(userErr); recordLogininfor(userName, LoginLog.FAIL, "用户密码错误"); throw new BizException("登陆失败,可尝试登陆次数为:" + (3 - (loginErrorCount))); } } } } // 获取用户角色和菜单权限 List<SysMenuVO> sysMenuList = sysMenuDao.listVisibleByUserId(user.getId()); // 登陆 StpUtil.login(user.getId()); SaTokenInfo tokenInfo = StpUtil.getTokenInfo(); recordLogininfor(userName, LoginLog.SUCCESS, "登陆成功"); //一旦有登陆成功的,将错误次数置空 user.setLastLoginErrorTime(null); user.setLoginStatus("1"); user.setLoginErrorCount(0); sysUserDao.updateLogin(user); return new LoginResponse(tokenInfo.getTokenName(), tokenInfo.getTokenValue(), user.getUserName(), list2tree(sysMenuList), user.getId()); } //层级关系转化 public List<SysMenuVO> list2tree(List<SysMenuVO> list) { List<SysMenuVO> tree = new ArrayList<SysMenuVO>(); for (SysMenuVO permission : list) { if (0 == permission.getPid().longValue()) { tree.add(permission); } for (SysMenuVO child : list) { if (permission.getId().longValue() == child.getPid().longValue()) { child.setpName(permission.getName()); if (null == permission.getChild()) { permission.setChild(new ArrayList<SysMenuVO>()); } permission.getChild().add(child); } } } return tree; } /** * 记录登录信息 */ public void recordLogininfor(String username, String status, String message) { LoginLog loginLog = new LoginLog(); loginLog.setLoginTime(new Date()); loginLog.setUserName(username); loginLog.setAddress(IpUtils.getIpAddr(ServletUtils.getRequest())); loginLog.setComment(message); loginLog.setStatus(status); loginLogMapper.insert(loginLog); }