ruoyi-admin/src/main/resources/i18n/messages.properties
@@ -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}个字符之间 ruoyi-admin/src/main/resources/i18n/messages_en_US.properties
@@ -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 ruoyi-admin/src/main/resources/i18n/messages_zh_CN.properties
@@ -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}个字符之间 ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java
@@ -84,6 +84,21 @@ Integer CAPTCHA_EXPIRATION = 2; /** * 登陆错误 redis key */ String LOGIN_ERROR = "login_error:"; /** * 登录错误次数 */ Integer LOGIN_ERROR_NUMBER = 5; /** * 登录错误限制时间(分钟) */ Integer LOGIN_ERROR_LIMIT_TIME = 10; /** * 令牌 */ String TOKEN = "token"; ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserException.java
@@ -10,7 +10,7 @@ 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); } } ruoyi-framework/src/main/java/com/ruoyi/framework/security/handle/LogoutSuccessHandlerImpl.java
@@ -7,6 +7,7 @@ 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 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))); } } ruoyi-system/src/main/java/com/ruoyi/system/service/SysLoginService.java
@@ -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.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 javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import java.util.concurrent.TimeUnit; /** * 登录校验方法 @@ -62,6 +64,13 @@ 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 @@ .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); ruoyi-system/src/main/java/com/ruoyi/system/service/impl/UserDetailsServiceImpl.java
@@ -3,7 +3,7 @@ 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 @@ 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);