update 用户登录 支持校验错误次数锁定登录
This commit is contained in:
parent
5322f5f707
commit
e8ee5ad691
@ -2,12 +2,12 @@
|
||||
not.null=* 必须填写
|
||||
user.jcaptcha.error=验证码错误
|
||||
user.jcaptcha.expire=验证码已失效
|
||||
user.not.exists=用户不存在/密码错误
|
||||
user.not.exists=对不起, 您的账号:{0} 不存在.
|
||||
user.password.not.match=用户不存在/密码错误
|
||||
user.password.retry.limit.count=密码输入错误{0}次
|
||||
user.password.retry.limit.exceed=密码输入错误{0}次,帐户锁定10分钟
|
||||
user.password.delete=对不起,您的账号已被删除
|
||||
user.blocked=用户已封禁,请联系管理员
|
||||
user.password.retry.limit.exceed=密码错误次数过多,帐户锁定{0}分钟
|
||||
user.password.delete=对不起,您的账号:{0} 已被删除
|
||||
user.blocked=对不起,您的账号:{0} 已禁用,请联系管理员
|
||||
role.blocked=角色已封禁,请联系管理员
|
||||
user.logout.success=退出成功
|
||||
length.not.valid=长度必须在{min}到{max}个字符之间
|
||||
|
@ -2,12 +2,12 @@
|
||||
not.null=* Required fill in
|
||||
user.jcaptcha.error=Captcha error
|
||||
user.jcaptcha.expire=Captcha invalid
|
||||
user.not.exists=User does not exist/Password error
|
||||
user.not.exists=Sorry, your account: {0} does not exist
|
||||
user.password.not.match=User does not exist/Password error
|
||||
user.password.retry.limit.count=Password input error {0} times
|
||||
user.password.retry.limit.exceed=Password input error {0} times, account locked for 10 minutes
|
||||
user.password.delete=Sorry, your account has been deleted
|
||||
user.blocked=User disabled,please contact administrators
|
||||
user.password.retry.limit.exceed=Too many password errors, account locked for {0} minutes
|
||||
user.password.delete=Sorry, your account:{0} has been deleted
|
||||
user.blocked=Sorry, your account: {0} has been disabled. Please contact the administrator
|
||||
role.blocked=Role disabled,please contact administrators
|
||||
user.logout.success=Exit successful
|
||||
length.not.valid=The length must be between {min} and {max} characters
|
||||
|
@ -2,12 +2,12 @@
|
||||
not.null=* 必须填写
|
||||
user.jcaptcha.error=验证码错误
|
||||
user.jcaptcha.expire=验证码已失效
|
||||
user.not.exists=用户不存在/密码错误
|
||||
user.not.exists=对不起, 您的账号:{0} 不存在.
|
||||
user.password.not.match=用户不存在/密码错误
|
||||
user.password.retry.limit.count=密码输入错误{0}次
|
||||
user.password.retry.limit.exceed=密码输入错误{0}次,帐户锁定10分钟
|
||||
user.password.delete=对不起,您的账号已被删除
|
||||
user.blocked=用户已封禁,请联系管理员
|
||||
user.password.retry.limit.exceed=密码错误次数过多,帐户锁定{0}分钟
|
||||
user.password.delete=对不起,您的账号:{0} 已被删除
|
||||
user.blocked=对不起,您的账号:{0} 已禁用,请联系管理员
|
||||
role.blocked=角色已封禁,请联系管理员
|
||||
user.logout.success=退出成功
|
||||
length.not.valid=长度必须在{min}到{max}个字符之间
|
||||
|
@ -83,6 +83,21 @@ public interface Constants {
|
||||
*/
|
||||
Integer CAPTCHA_EXPIRATION = 2;
|
||||
|
||||
/**
|
||||
* 登陆错误 redis key
|
||||
*/
|
||||
String LOGIN_ERROR = "login_error:";
|
||||
|
||||
/**
|
||||
* 登录错误次数
|
||||
*/
|
||||
Integer LOGIN_ERROR_NUMBER = 5;
|
||||
|
||||
/**
|
||||
* 登录错误限制时间(分钟)
|
||||
*/
|
||||
Integer LOGIN_ERROR_LIMIT_TIME = 10;
|
||||
|
||||
/**
|
||||
* 令牌
|
||||
*/
|
||||
|
@ -10,7 +10,7 @@ import com.ruoyi.common.exception.base.BaseException;
|
||||
public class UserException extends BaseException {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public UserException(String code, Object[] args) {
|
||||
public UserException(String code, Object... args) {
|
||||
super("user", code, args, null);
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ import com.ruoyi.common.core.domain.model.LoginUser;
|
||||
import com.ruoyi.common.core.service.LogininforService;
|
||||
import com.ruoyi.common.core.service.TokenService;
|
||||
import com.ruoyi.common.utils.JsonUtils;
|
||||
import com.ruoyi.common.utils.MessageUtils;
|
||||
import com.ruoyi.common.utils.ServletUtils;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@ -40,14 +41,15 @@ public class LogoutSuccessHandlerImpl implements LogoutSuccessHandler {
|
||||
public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication)
|
||||
throws IOException, ServletException {
|
||||
LoginUser loginUser = tokenService.getLoginUser(request);
|
||||
if (StringUtils.isNotNull(loginUser)) {
|
||||
String message = MessageUtils.message("user.logout.success");
|
||||
if (StringUtils.isNotNull(loginUser)) {
|
||||
String userName = loginUser.getUsername();
|
||||
// 删除用户缓存记录
|
||||
tokenService.delLoginUser(loginUser.getToken());
|
||||
// 记录用户退出日志
|
||||
asyncService.recordLogininfor(userName, Constants.LOGOUT, "退出成功", request);
|
||||
asyncService.recordLogininfor(userName, Constants.LOGOUT, message, request);
|
||||
}
|
||||
ServletUtils.renderString(response, JsonUtils.toJsonString(AjaxResult.error(HttpStatus.HTTP_OK, "退出成功")));
|
||||
ServletUtils.renderString(response, JsonUtils.toJsonString(AjaxResult.error(HttpStatus.HTTP_OK, message)));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.ruoyi.system.service;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.ruoyi.common.constant.Constants;
|
||||
import com.ruoyi.common.core.domain.entity.SysUser;
|
||||
import com.ruoyi.common.core.domain.model.LoginUser;
|
||||
@ -8,7 +9,7 @@ import com.ruoyi.common.core.service.TokenService;
|
||||
import com.ruoyi.common.exception.ServiceException;
|
||||
import com.ruoyi.common.exception.user.CaptchaException;
|
||||
import com.ruoyi.common.exception.user.CaptchaExpireException;
|
||||
import com.ruoyi.common.exception.user.UserPasswordNotMatchException;
|
||||
import com.ruoyi.common.exception.user.UserException;
|
||||
import com.ruoyi.common.utils.DateUtils;
|
||||
import com.ruoyi.common.utils.MessageUtils;
|
||||
import com.ruoyi.common.utils.RedisUtils;
|
||||
@ -22,6 +23,7 @@ import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* 登录校验方法
|
||||
@ -62,6 +64,13 @@ public class SysLoginService {
|
||||
if (captchaOnOff) {
|
||||
validateCaptcha(username, code, uuid, request);
|
||||
}
|
||||
// 获取用户登录错误次数(可自定义限制策略 例如: key + username + ip)
|
||||
Integer errorNumber = RedisUtils.getCacheObject(Constants.LOGIN_ERROR + username);
|
||||
// 锁定时间内登录 则踢出
|
||||
if (ObjectUtil.isNotNull(errorNumber) && errorNumber.equals(Constants.LOGIN_ERROR_NUMBER)) {
|
||||
asyncService.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.retry.limit.exceed", Constants.LOGIN_ERROR_LIMIT_TIME), request);
|
||||
throw new UserException("user.password.retry.limit.exceed", Constants.LOGIN_ERROR_LIMIT_TIME);
|
||||
}
|
||||
// 用户验证
|
||||
Authentication authentication = null;
|
||||
try {
|
||||
@ -70,13 +79,26 @@ public class SysLoginService {
|
||||
.authenticate(new UsernamePasswordAuthenticationToken(username, password));
|
||||
} catch (Exception e) {
|
||||
if (e instanceof BadCredentialsException) {
|
||||
asyncService.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match"), request);
|
||||
throw new UserPasswordNotMatchException();
|
||||
// 是否第一次
|
||||
errorNumber = ObjectUtil.isNull(errorNumber) ? 1 : errorNumber + 1;
|
||||
// 达到规定错误次数 则锁定登录
|
||||
if (errorNumber.equals(Constants.LOGIN_ERROR_NUMBER)) {
|
||||
RedisUtils.setCacheObject(Constants.LOGIN_ERROR + username, errorNumber, Constants.LOGIN_ERROR_LIMIT_TIME, TimeUnit.MINUTES);
|
||||
asyncService.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.retry.limit.exceed", Constants.LOGIN_ERROR_LIMIT_TIME), request);
|
||||
throw new UserException("user.password.retry.limit.exceed", Constants.LOGIN_ERROR_LIMIT_TIME);
|
||||
} else {
|
||||
// 未达到规定错误次数 则递增
|
||||
RedisUtils.setCacheObject(Constants.LOGIN_ERROR + username, errorNumber);
|
||||
asyncService.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.retry.limit.count", errorNumber), request);
|
||||
throw new UserException("user.password.retry.limit.count", errorNumber);
|
||||
}
|
||||
} else {
|
||||
asyncService.recordLogininfor(username, Constants.LOGIN_FAIL, e.getMessage(), request);
|
||||
throw new ServiceException(e.getMessage());
|
||||
}
|
||||
}
|
||||
// 登录成功 清空错误次数
|
||||
RedisUtils.deleteObject(Constants.LOGIN_ERROR + username);
|
||||
asyncService.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"), request);
|
||||
LoginUser loginUser = (LoginUser) authentication.getPrincipal();
|
||||
recordLoginInfo(loginUser.getUserId(), username);
|
||||
|
@ -3,7 +3,7 @@ package com.ruoyi.system.service.impl;
|
||||
import com.ruoyi.common.core.domain.entity.SysUser;
|
||||
import com.ruoyi.common.core.domain.model.LoginUser;
|
||||
import com.ruoyi.common.enums.UserStatus;
|
||||
import com.ruoyi.common.exception.ServiceException;
|
||||
import com.ruoyi.common.exception.user.UserException;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import com.ruoyi.system.service.ISysUserService;
|
||||
import com.ruoyi.system.service.SysPermissionService;
|
||||
@ -34,13 +34,13 @@ public class UserDetailsServiceImpl implements UserDetailsService {
|
||||
SysUser user = userService.selectUserByUserName(username);
|
||||
if (StringUtils.isNull(user)) {
|
||||
log.info("登录用户:{} 不存在.", username);
|
||||
throw new ServiceException("登录用户:" + username + " 不存在");
|
||||
throw new UserException("user.not.exists", username);
|
||||
} else if (UserStatus.DELETED.getCode().equals(user.getDelFlag())) {
|
||||
log.info("登录用户:{} 已被删除.", username);
|
||||
throw new ServiceException("对不起,您的账号:" + username + " 已被删除");
|
||||
throw new UserException("user.password.delete", username);
|
||||
} else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) {
|
||||
log.info("登录用户:{} 已被停用.", username);
|
||||
throw new ServiceException("对不起,您的账号:" + username + " 已停用");
|
||||
throw new UserException("user.blocked", username);
|
||||
}
|
||||
|
||||
return createLoginUser(user);
|
||||
|
Loading…
x
Reference in New Issue
Block a user