java实现登陆失败n次锁定账户,y分钟后自动解锁,两次失败间隔时间过大则不计次数(含redis处理)
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);
}