疯狂的狮子Li
2022-04-17 eb1047a149112cd6751808b326cd449345453174
update 优化登录失败相关部分代码结构
已添加1个文件
已修改1个文件
136 ■■■■■ 文件已修改
ruoyi-common/src/main/java/com/ruoyi/common/enums/LoginType.java 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/SysLoginService.java 97 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/enums/LoginType.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,39 @@
package com.ruoyi.common.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
 * ç™»å½•类型
 *
 * @author Lion Li
 */
@Getter
@AllArgsConstructor
public enum LoginType {
    /**
     * å¯†ç ç™»å½•
     */
    PASSWORD("user.password.retry.limit.exceed", "user.password.retry.limit.count"),
    /**
     * çŸ­ä¿¡ç™»å½•
     */
    SMS("sms.code.retry.limit.exceed", "sms.code.retry.limit.count"),
    /**
     * å°ç¨‹åºç™»å½•
     */
    XCX("", "");
    /**
     * ç™»å½•重试超出限制提示
     */
    final String retryLimitExceed;
    /**
     * ç™»å½•重试限制计数提示
     */
    final String retryLimitCount;
}
ruoyi-system/src/main/java/com/ruoyi/system/service/SysLoginService.java
@@ -11,6 +11,7 @@
import com.ruoyi.common.core.domain.model.XcxLoginUser;
import com.ruoyi.common.core.service.LogininforService;
import com.ruoyi.common.enums.DeviceType;
import com.ruoyi.common.enums.LoginType;
import com.ruoyi.common.enums.UserStatus;
import com.ruoyi.common.exception.user.CaptchaException;
import com.ruoyi.common.exception.user.CaptchaExpireException;
@@ -28,6 +29,7 @@
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;
/**
 * ç™»å½•校验方法
@@ -60,35 +62,8 @@
        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);
        }
        SysUser user = loadUserByUsername(username);
        if (!BCrypt.checkpw(password, user.getPassword())) {
            // æ˜¯å¦ç¬¬ä¸€æ¬¡
            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);
            }
        }
        // ç™»å½•成功 æ¸…空错误次数
        RedisUtils.deleteObject(Constants.LOGIN_ERROR + username);
        checkLogin(LoginType.PASSWORD, username, () -> !BCrypt.checkpw(password, user.getPassword()));
        // æ­¤å¤„可根据登录用户的数据不同 è‡ªè¡Œåˆ›å»º loginUser
        LoginUser loginUser = buildLoginUser(user);
        // ç”Ÿæˆtoken
@@ -104,33 +79,7 @@
        SysUser user = loadUserByPhonenumber(phonenumber);
        HttpServletRequest request = ServletUtils.getRequest();
        // èŽ·å–ç”¨æˆ·ç™»å½•é”™è¯¯æ¬¡æ•°(可自定义限制策略 ä¾‹å¦‚: key + username + ip)
        Integer errorNumber = RedisUtils.getCacheObject(Constants.LOGIN_ERROR + user.getUserName());
        // é”å®šæ—¶é—´å†…登录 åˆ™è¸¢å‡º
        if (ObjectUtil.isNotNull(errorNumber) && errorNumber.equals(Constants.LOGIN_ERROR_NUMBER)) {
            asyncService.recordLogininfor(user.getUserName(), Constants.LOGIN_FAIL, MessageUtils.message("sms.code.retry.limit.exceed", Constants.LOGIN_ERROR_LIMIT_TIME), request);
            throw new UserException("sms.code.retry.limit.exceed", Constants.LOGIN_ERROR_LIMIT_TIME);
        }
        if (!validateSmsCode(phonenumber, smsCode)) {
            // æ˜¯å¦ç¬¬ä¸€æ¬¡
            errorNumber = ObjectUtil.isNull(errorNumber) ? 1 : errorNumber + 1;
            // è¾¾åˆ°è§„定错误次数 åˆ™é”å®šç™»å½•
            if (errorNumber.equals(Constants.LOGIN_ERROR_NUMBER)) {
                RedisUtils.setCacheObject(Constants.LOGIN_ERROR + user.getUserName(), errorNumber, Constants.LOGIN_ERROR_LIMIT_TIME, TimeUnit.MINUTES);
                asyncService.recordLogininfor(user.getUserName(), Constants.LOGIN_FAIL, MessageUtils.message("sms.code.retry.limit.exceed", Constants.LOGIN_ERROR_LIMIT_TIME), request);
                throw new UserException("sms.code.retry.limit.exceed", Constants.LOGIN_ERROR_LIMIT_TIME);
            } else {
                // æœªè¾¾åˆ°è§„定错误次数 åˆ™é€’增
                RedisUtils.setCacheObject(Constants.LOGIN_ERROR + user.getUserName(), errorNumber);
                asyncService.recordLogininfor(user.getUserName(), Constants.LOGIN_FAIL, MessageUtils.message("sms.code.retry.limit.count", errorNumber), request);
                throw new UserException("sms.code.retry.limit.count", errorNumber);
            }
        }
        // ç™»å½•成功 æ¸…空错误次数
        RedisUtils.deleteObject(Constants.LOGIN_ERROR + user.getUserName());
        checkLogin(LoginType.SMS, user.getUserName(), () -> !validateSmsCode(phonenumber, smsCode));
        // æ­¤å¤„可根据登录用户的数据不同 è‡ªè¡Œåˆ›å»º loginUser
        LoginUser loginUser = buildLoginUser(user);
        // ç”Ÿæˆtoken
@@ -275,4 +224,42 @@
        sysUser.setUpdateBy(username);
        userService.updateUserProfile(sysUser);
    }
    /**
     * ç™»å½•校验
     */
    private void checkLogin(LoginType loginType, String username, Supplier<Boolean> supplier) {
        HttpServletRequest request = ServletUtils.getRequest();
        String errorKey = Constants.LOGIN_ERROR + username;
        Integer errorLimitTime = Constants.LOGIN_ERROR_LIMIT_TIME;
        Integer setErrorNumber = Constants.LOGIN_ERROR_NUMBER;
        String loginFail = Constants.LOGIN_FAIL;
        // èŽ·å–ç”¨æˆ·ç™»å½•é”™è¯¯æ¬¡æ•°(可自定义限制策略 ä¾‹å¦‚: key + username + ip)
        Integer errorNumber = RedisUtils.getCacheObject(errorKey);
        // é”å®šæ—¶é—´å†…登录 åˆ™è¸¢å‡º
        if (ObjectUtil.isNotNull(errorNumber) && errorNumber.equals(setErrorNumber)) {
            asyncService.recordLogininfor(username, loginFail, MessageUtils.message(loginType.getRetryLimitExceed(), errorLimitTime), request);
            throw new UserException(loginType.getRetryLimitExceed(), errorLimitTime);
        }
        if (supplier.get()) {
            // æ˜¯å¦ç¬¬ä¸€æ¬¡
            errorNumber = ObjectUtil.isNull(errorNumber) ? 1 : errorNumber + 1;
            // è¾¾åˆ°è§„定错误次数 åˆ™é”å®šç™»å½•
            if (errorNumber.equals(setErrorNumber)) {
                RedisUtils.setCacheObject(errorKey, errorNumber, errorLimitTime, TimeUnit.MINUTES);
                asyncService.recordLogininfor(username, loginFail, MessageUtils.message(loginType.getRetryLimitExceed(), errorLimitTime), request);
                throw new UserException(loginType.getRetryLimitExceed(), errorLimitTime);
            } else {
                // æœªè¾¾åˆ°è§„定错误次数 åˆ™é€’增
                RedisUtils.setCacheObject(errorKey, errorNumber);
                asyncService.recordLogininfor(username, loginFail, MessageUtils.message(loginType.getRetryLimitCount(), errorNumber), request);
                throw new UserException(loginType.getRetryLimitCount(), errorNumber);
            }
        }
        // ç™»å½•成功 æ¸…空错误次数
        RedisUtils.deleteObject(errorKey);
    }
}