login模块,安全增强:防止暴力破解,用户错误连续超过5次,锁定30分钟

This commit is contained in:
duandazhi 2022-01-21 20:07:06 +08:00
parent d511f1bd94
commit 3ec7d8f5cb
2 changed files with 53 additions and 4 deletions

View File

@ -1,5 +1,7 @@
package com.ruoyi.auth.service; package com.ruoyi.auth.service;
import com.ruoyi.common.core.constant.CacheConstants;
import com.ruoyi.common.redis.service.RedisService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import com.ruoyi.common.core.constant.Constants; import com.ruoyi.common.core.constant.Constants;
@ -18,9 +20,12 @@ import com.ruoyi.system.api.domain.SysLogininfor;
import com.ruoyi.system.api.domain.SysUser; import com.ruoyi.system.api.domain.SysUser;
import com.ruoyi.system.api.model.LoginUser; import com.ruoyi.system.api.model.LoginUser;
import java.util.Date;
import java.util.concurrent.TimeUnit;
/** /**
* 登录校验方法 * 登录校验方法
* *
* @author ruoyi * @author ruoyi
*/ */
@Component @Component
@ -32,6 +37,9 @@ public class SysLoginService
@Autowired @Autowired
private RemoteUserService remoteUserService; private RemoteUserService remoteUserService;
@Autowired
private RedisService redisService;
/** /**
* 登录 * 登录
*/ */
@ -87,6 +95,7 @@ public class SysLoginService
recordLogininfor(username, Constants.LOGIN_FAIL, "用户密码错误"); recordLogininfor(username, Constants.LOGIN_FAIL, "用户密码错误");
throw new ServiceException("用户不存在/密码错误"); throw new ServiceException("用户不存在/密码错误");
} }
recordLogininfor(username, Constants.LOGIN_SUCCESS, "登录成功"); recordLogininfor(username, Constants.LOGIN_SUCCESS, "登录成功");
return userInfo; return userInfo;
} }
@ -133,7 +142,7 @@ public class SysLoginService
/** /**
* 记录登录信息 * 记录登录信息
* *
* @param username 用户名 * @param username 用户名
* @param status 状态 * @param status 状态
* @param message 消息内容 * @param message 消息内容
@ -155,5 +164,40 @@ public class SysLoginService
logininfor.setStatus("1"); logininfor.setStatus("1");
} }
remoteLogService.saveLogininfor(logininfor, SecurityConstants.INNER); remoteLogService.saveLogininfor(logininfor, SecurityConstants.INNER);
//记录错误次数 防止无限重试进行暴力破解
recordLoginErrorTimes(username, status);
} }
}
/**
* @author dazer
* @date 2022-01-21
* 记录username错误次数超过指定次数 锁定xx分钟防止暴力破解
* @param username 登录用户名
* @param status {@link Constants#LOGIN_SUCCESS}
* {@link Constants#LOGIN_FAIL}
*/
private void recordLoginErrorTimes(String username, String status)
{
String loginErrorTimesKey = CacheConstants.REDIS_KEY_ERROR_TIMES + username;
Long redisKeyTimeout = 30L;
long maxErrorTimes = 5L;
if (Constants.LOGIN_SUCCESS.equals(status)) {
redisService.deleteObject(loginErrorTimesKey);
} else if (Constants.LOGIN_FAIL.equals(status)) {
Integer errorTimes = redisService.getCacheObject(loginErrorTimesKey);
if (errorTimes == null) {
errorTimes = 0;
}
// 登录错误进行累加错误次数
errorTimes++;
// 登录错误缓存30分钟
redisService.setCacheObject(loginErrorTimesKey, errorTimes, redisKeyTimeout, TimeUnit.MINUTES);
// 连续错误5次进行账号锁定
if (errorTimes >= maxErrorTimes) {
throw new ServiceException("用户名密码错误次数已达上限,账号已被锁定请" + redisKeyTimeout + "分钟后再试!");
}
}
}
}

View File

@ -2,7 +2,7 @@ package com.ruoyi.common.core.constant;
/** /**
* 缓存的key 常量 * 缓存的key 常量
* *
* @author ruoyi * @author ruoyi
*/ */
public class CacheConstants public class CacheConstants
@ -21,4 +21,9 @@ public class CacheConstants
* 权限缓存前缀 * 权限缓存前缀
*/ */
public final static String LOGIN_TOKEN_KEY = "login_tokens:"; public final static String LOGIN_TOKEN_KEY = "login_tokens:";
/**
* username登录错误次数的 redis key
*/
public final static String REDIS_KEY_ERROR_TIMES = "login:error:times:";
} }