diff --git a/ruoyi-auth/src/main/java/com/ruoyi/auth/service/SysLoginService.java b/ruoyi-auth/src/main/java/com/ruoyi/auth/service/SysLoginService.java index 489399397..37d5e46a2 100644 --- a/ruoyi-auth/src/main/java/com/ruoyi/auth/service/SysLoginService.java +++ b/ruoyi-auth/src/main/java/com/ruoyi/auth/service/SysLoginService.java @@ -8,13 +8,9 @@ import com.ruoyi.common.core.constant.UserConstants; import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.enums.UserStatus; import com.ruoyi.common.core.exception.ServiceException; -import com.ruoyi.common.core.utils.ServletUtils; import com.ruoyi.common.core.utils.StringUtils; -import com.ruoyi.common.core.utils.ip.IpUtils; import com.ruoyi.common.security.utils.SecurityUtils; -import com.ruoyi.system.api.RemoteLogService; import com.ruoyi.system.api.RemoteUserService; -import com.ruoyi.system.api.domain.SysLogininfor; import com.ruoyi.system.api.domain.SysUser; import com.ruoyi.system.api.model.LoginUser; @@ -27,10 +23,13 @@ import com.ruoyi.system.api.model.LoginUser; public class SysLoginService { @Autowired - private RemoteLogService remoteLogService; + private RemoteUserService remoteUserService; @Autowired - private RemoteUserService remoteUserService; + private SysPasswordService passwordService; + + @Autowired + private SysRecordLogService recordLogService; /** * 登录 @@ -40,21 +39,21 @@ public class SysLoginService // 用户名或密码为空 错误 if (StringUtils.isAnyBlank(username, password)) { - recordLogininfor(username, Constants.LOGIN_FAIL, "用户/密码必须填写"); + recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "用户/密码必须填写"); throw new ServiceException("用户/密码必须填写"); } // 密码如果不在指定范围内 错误 if (password.length() < UserConstants.PASSWORD_MIN_LENGTH || password.length() > UserConstants.PASSWORD_MAX_LENGTH) { - recordLogininfor(username, Constants.LOGIN_FAIL, "用户密码不在指定范围"); + recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "用户密码不在指定范围"); throw new ServiceException("用户密码不在指定范围"); } // 用户名不在指定范围内 错误 if (username.length() < UserConstants.USERNAME_MIN_LENGTH || username.length() > UserConstants.USERNAME_MAX_LENGTH) { - recordLogininfor(username, Constants.LOGIN_FAIL, "用户名不在指定范围"); + recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "用户名不在指定范围"); throw new ServiceException("用户名不在指定范围"); } // 查询用户信息 @@ -67,33 +66,29 @@ public class SysLoginService if (StringUtils.isNull(userResult) || StringUtils.isNull(userResult.getData())) { - recordLogininfor(username, Constants.LOGIN_FAIL, "登录用户不存在"); + recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "登录用户不存在"); throw new ServiceException("登录用户:" + username + " 不存在"); } LoginUser userInfo = userResult.getData(); SysUser user = userResult.getData().getSysUser(); if (UserStatus.DELETED.getCode().equals(user.getDelFlag())) { - recordLogininfor(username, Constants.LOGIN_FAIL, "对不起,您的账号已被删除"); + recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "对不起,您的账号已被删除"); throw new ServiceException("对不起,您的账号:" + username + " 已被删除"); } if (UserStatus.DISABLE.getCode().equals(user.getStatus())) { - recordLogininfor(username, Constants.LOGIN_FAIL, "用户已停用,请联系管理员"); + recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "用户已停用,请联系管理员"); throw new ServiceException("对不起,您的账号:" + username + " 已停用"); } - if (!SecurityUtils.matchesPassword(password, user.getPassword())) - { - recordLogininfor(username, Constants.LOGIN_FAIL, "用户密码错误"); - throw new ServiceException("用户不存在/密码错误"); - } - recordLogininfor(username, Constants.LOGIN_SUCCESS, "登录成功"); + passwordService.validate(user, password); + recordLogService.recordLogininfor(username, Constants.LOGIN_SUCCESS, "登录成功"); return userInfo; } public void logout(String loginName) { - recordLogininfor(loginName, Constants.LOGOUT, "退出成功"); + recordLogService.recordLogininfor(loginName, Constants.LOGOUT, "退出成功"); } /** @@ -128,32 +123,6 @@ public class SysLoginService { throw new ServiceException(registerResult.getMsg()); } - recordLogininfor(username, Constants.REGISTER, "注册成功"); - } - - /** - * 记录登录信息 - * - * @param username 用户名 - * @param status 状态 - * @param message 消息内容 - * @return - */ - public void recordLogininfor(String username, String status, String message) - { - SysLogininfor logininfor = new SysLogininfor(); - logininfor.setUserName(username); - logininfor.setIpaddr(IpUtils.getIpAddr(ServletUtils.getRequest())); - logininfor.setMsg(message); - // 日志状态 - if (StringUtils.equalsAny(status, Constants.LOGIN_SUCCESS, Constants.LOGOUT, Constants.REGISTER)) - { - logininfor.setStatus(Constants.LOGIN_SUCCESS_STATUS); - } - else if (Constants.LOGIN_FAIL.equals(status)) - { - logininfor.setStatus(Constants.LOGIN_FAIL_STATUS); - } - remoteLogService.saveLogininfor(logininfor, SecurityConstants.INNER); + recordLogService.recordLogininfor(username, Constants.REGISTER, "注册成功"); } -} \ No newline at end of file +} diff --git a/ruoyi-auth/src/main/java/com/ruoyi/auth/service/SysPasswordService.java b/ruoyi-auth/src/main/java/com/ruoyi/auth/service/SysPasswordService.java new file mode 100644 index 000000000..06e111a74 --- /dev/null +++ b/ruoyi-auth/src/main/java/com/ruoyi/auth/service/SysPasswordService.java @@ -0,0 +1,85 @@ +package com.ruoyi.auth.service; + +import java.util.concurrent.TimeUnit; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import com.ruoyi.common.core.constant.CacheConstants; +import com.ruoyi.common.core.constant.Constants; +import com.ruoyi.common.core.exception.ServiceException; +import com.ruoyi.common.redis.service.RedisService; +import com.ruoyi.common.security.utils.SecurityUtils; +import com.ruoyi.system.api.domain.SysUser; + +/** + * 登录密码方法 + * + * @author ruoyi + */ +@Component +public class SysPasswordService +{ + @Autowired + private RedisService redisService; + + private int maxRetryCount = CacheConstants.passwordMaxRetryCount; + + private Long lockTime = CacheConstants.passwordLockTime; + + @Autowired + private SysRecordLogService recordLogService; + + /** + * 登录账户密码错误次数缓存键名 + * + * @param username 用户名 + * @return 缓存键key + */ + private String getCacheKey(String username) + { + return CacheConstants.PWD_ERR_CNT_KEY + username; + } + + public void validate(SysUser user, String password) + { + String username = user.getUserName(); + + Integer retryCount = redisService.getCacheObject(getCacheKey(username)); + + if (retryCount == null) + { + retryCount = 0; + } + + if (retryCount >= Integer.valueOf(maxRetryCount).intValue()) + { + String errMsg = String.format("密码输入错误%s次,帐户锁定%s分钟", maxRetryCount, lockTime); + recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL,errMsg); + throw new ServiceException(errMsg); + } + + if (!matches(user, password)) + { + retryCount = retryCount + 1; + recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, String.format("密码输入错误%s次", maxRetryCount)); + redisService.setCacheObject(getCacheKey(username), retryCount, lockTime, TimeUnit.MINUTES); + throw new ServiceException("用户不存在/密码错误"); + } + else + { + clearLoginRecordCache(username); + } + } + + public boolean matches(SysUser user, String rawPassword) + { + return SecurityUtils.matchesPassword(rawPassword, user.getPassword()); + } + + public void clearLoginRecordCache(String loginName) + { + if (redisService.hasKey(getCacheKey(loginName))) + { + redisService.deleteObject(getCacheKey(loginName)); + } + } +} diff --git a/ruoyi-auth/src/main/java/com/ruoyi/auth/service/SysRecordLogService.java b/ruoyi-auth/src/main/java/com/ruoyi/auth/service/SysRecordLogService.java new file mode 100644 index 000000000..21d6ac971 --- /dev/null +++ b/ruoyi-auth/src/main/java/com/ruoyi/auth/service/SysRecordLogService.java @@ -0,0 +1,49 @@ +package com.ruoyi.auth.service; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import com.ruoyi.common.core.constant.Constants; +import com.ruoyi.common.core.constant.SecurityConstants; +import com.ruoyi.common.core.utils.ServletUtils; +import com.ruoyi.common.core.utils.StringUtils; +import com.ruoyi.common.core.utils.ip.IpUtils; +import com.ruoyi.system.api.RemoteLogService; +import com.ruoyi.system.api.domain.SysLogininfor; + +/** + * 记录日志方法 + * + * @author ruoyi + */ +@Component +public class SysRecordLogService +{ + @Autowired + private RemoteLogService remoteLogService; + + /** + * 记录登录信息 + * + * @param username 用户名 + * @param status 状态 + * @param message 消息内容 + * @return + */ + public void recordLogininfor(String username, String status, String message) + { + SysLogininfor logininfor = new SysLogininfor(); + logininfor.setUserName(username); + logininfor.setIpaddr(IpUtils.getIpAddr(ServletUtils.getRequest())); + logininfor.setMsg(message); + // 日志状态 + if (StringUtils.equalsAny(status, Constants.LOGIN_SUCCESS, Constants.LOGOUT, Constants.REGISTER)) + { + logininfor.setStatus(Constants.LOGIN_SUCCESS_STATUS); + } + else if (Constants.LOGIN_FAIL.equals(status)) + { + logininfor.setStatus(Constants.LOGIN_FAIL_STATUS); + } + remoteLogService.saveLogininfor(logininfor, SecurityConstants.INNER); + } +} diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/CacheConstants.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/CacheConstants.java index 913a891d7..e63d95ecf 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/CacheConstants.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/CacheConstants.java @@ -1,7 +1,7 @@ package com.ruoyi.common.core.constant; /** - * 缓存的key 常量 + * 缓存常量信息 * * @author ruoyi */ @@ -17,8 +17,38 @@ public class CacheConstants */ public final static long REFRESH_TIME = 120; + /** + * 密码最大错误次数 + */ + public final static int passwordMaxRetryCount = 5; + + /** + * 密码锁定时间,默认10(分钟) + */ + public final static long passwordLockTime = 10; + /** * 权限缓存前缀 */ public final static String LOGIN_TOKEN_KEY = "login_tokens:"; + + /** + * 验证码 redis key + */ + public static final String CAPTCHA_CODE_KEY = "captcha_codes:"; + + /** + * 参数管理 cache key + */ + public static final String SYS_CONFIG_KEY = "sys_config:"; + + /** + * 字典管理 cache key + */ + public static final String SYS_DICT_KEY = "sys_dict:"; + + /** + * 登录账户密码错误次数 redis key + */ + public static final String PWD_ERR_CNT_KEY = "pwd_err_cnt:"; } diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/Constants.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/Constants.java index 038c221e0..69031a351 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/Constants.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/Constants.java @@ -102,27 +102,11 @@ public class Constants */ public static final String IS_ASC = "isAsc"; - /** - * 验证码 redis key - */ - public static final String CAPTCHA_CODE_KEY = "captcha_codes:"; - /** * 验证码有效期(分钟) */ public static final long CAPTCHA_EXPIRATION = 2; - - /** - * 参数管理 cache key - */ - public static final String SYS_CONFIG_KEY = "sys_config:"; - - /** - * 字典管理 cache key - */ - public static final String SYS_DICT_KEY = "sys_dict:"; - /** * 资源映射路径 前缀 */ diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/web/domain/AjaxResult.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/web/domain/AjaxResult.java index 626f4afbe..814b0c248 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/web/domain/AjaxResult.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/web/domain/AjaxResult.java @@ -1,6 +1,7 @@ package com.ruoyi.common.core.web.domain; import java.util.HashMap; +import java.util.Objects; import com.ruoyi.common.core.constant.HttpStatus; import com.ruoyi.common.core.utils.StringUtils; @@ -57,20 +58,6 @@ public class AjaxResult extends HashMap super.put(DATA_TAG, data); } } - - /** - * 方便链式调用 - * - * @param key - * @param value - * @return - */ - @Override - public AjaxResult put(String key, Object value) - { - super.put(key, value); - return this; - } /** * 返回成功消息 @@ -159,4 +146,38 @@ public class AjaxResult extends HashMap { return new AjaxResult(code, msg, null); } + + /** + * 是否为成功消息 + * + * @return 结果 + */ + public boolean isSuccess() + { + return !isError(); + } + + /** + * 是否为错误消息 + * + * @return 结果 + */ + public boolean isError() + { + return Objects.equals(HttpStatus.SUCCESS, this.get(CODE_TAG)); + } + + /** + * 方便链式调用 + * + * @param key + * @param value + * @return + */ + @Override + public AjaxResult put(String key, Object value) + { + super.put(key, value); + return this; + } } diff --git a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/utils/DictUtils.java b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/utils/DictUtils.java index 29e52e61c..2c8d18d6d 100644 --- a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/utils/DictUtils.java +++ b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/utils/DictUtils.java @@ -3,7 +3,7 @@ package com.ruoyi.common.security.utils; import java.util.Collection; import java.util.List; import com.alibaba.fastjson2.JSONArray; -import com.ruoyi.common.core.constant.Constants; +import com.ruoyi.common.core.constant.CacheConstants; import com.ruoyi.common.core.utils.SpringUtils; import com.ruoyi.common.core.utils.StringUtils; import com.ruoyi.common.redis.service.RedisService; @@ -58,7 +58,7 @@ public class DictUtils */ public static void clearDictCache() { - Collection keys = SpringUtils.getBean(RedisService.class).keys(Constants.SYS_DICT_KEY + "*"); + Collection keys = SpringUtils.getBean(RedisService.class).keys(CacheConstants.SYS_DICT_KEY + "*"); SpringUtils.getBean(RedisService.class).deleteObject(keys); } @@ -70,6 +70,6 @@ public class DictUtils */ public static String getCacheKey(String configKey) { - return Constants.SYS_DICT_KEY + configKey; + return CacheConstants.SYS_DICT_KEY + configKey; } } diff --git a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/service/impl/ValidateCodeServiceImpl.java b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/service/impl/ValidateCodeServiceImpl.java index bb4db0c01..4c130a932 100644 --- a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/service/impl/ValidateCodeServiceImpl.java +++ b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/service/impl/ValidateCodeServiceImpl.java @@ -9,6 +9,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.util.FastByteArrayOutputStream; import com.google.code.kaptcha.Producer; +import com.ruoyi.common.core.constant.CacheConstants; import com.ruoyi.common.core.constant.Constants; import com.ruoyi.common.core.exception.CaptchaException; import com.ruoyi.common.core.utils.StringUtils; @@ -55,7 +56,7 @@ public class ValidateCodeServiceImpl implements ValidateCodeService // 保存验证码信息 String uuid = IdUtils.simpleUUID(); - String verifyKey = Constants.CAPTCHA_CODE_KEY + uuid; + String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + uuid; String capStr = null, code = null; BufferedImage image = null; @@ -106,7 +107,7 @@ public class ValidateCodeServiceImpl implements ValidateCodeService { throw new CaptchaException("验证码已失效"); } - String verifyKey = Constants.CAPTCHA_CODE_KEY + uuid; + String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + uuid; String captcha = redisService.getCacheObject(verifyKey); redisService.deleteObject(verifyKey); diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysConfigServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysConfigServiceImpl.java index bbda508ab..c34d0fc45 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysConfigServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysConfigServiceImpl.java @@ -5,7 +5,7 @@ import java.util.List; import javax.annotation.PostConstruct; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import com.ruoyi.common.core.constant.Constants; +import com.ruoyi.common.core.constant.CacheConstants; import com.ruoyi.common.core.constant.UserConstants; import com.ruoyi.common.core.exception.ServiceException; import com.ruoyi.common.core.text.Convert; @@ -162,7 +162,7 @@ public class SysConfigServiceImpl implements ISysConfigService @Override public void clearConfigCache() { - Collection keys = redisService.keys(Constants.SYS_CONFIG_KEY + "*"); + Collection keys = redisService.keys(CacheConstants.SYS_CONFIG_KEY + "*"); redisService.deleteObject(keys); } @@ -202,6 +202,6 @@ public class SysConfigServiceImpl implements ISysConfigService */ private String getCacheKey(String configKey) { - return Constants.SYS_CONFIG_KEY + configKey; + return CacheConstants.SYS_CONFIG_KEY + configKey; } }