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; import javax.servlet.http.HttpServletRequest; /** * 登录密码方法 * * @author ruoyi */ @Component public class SysPasswordService { @Autowired private RedisService redisService; private int maxRetryCount = CacheConstants.PASSWORD_MAX_RETRY_COUNT; private Long lockTime = CacheConstants.PASSWORD_LOCK_TIME; @Autowired private SysRecordLogService recordLogService; /** * 登录账户密码错误次数缓存键名 * * @param username 用户名 * @return 缓存键key */ private String getCacheKey(String username) { return CacheConstants.PWD_ERR_CNT_KEY + username; } /** * 检查账号是否处于锁定状态(锁定期内直接抛出锁定提示)。 * 在限流之前调用,避免锁定提示被"登录尝试过于频繁"掩盖。 * * @param username 用户名 * @param request 请求 */ public void checkLocked(String username, HttpServletRequest request) { Integer retryCount = redisService.getIntegerCacheObject(getCacheKey(username)); if (retryCount != null && retryCount >= maxRetryCount) { String errMsg = String.format("密码输入错误%s次,帐户锁定%s分钟", maxRetryCount, lockTime); throw new ServiceException(errMsg); } } public void validate(SysUser user, String password, HttpServletRequest request) { String username = user.getUserName(); Integer retryCount = redisService.getIntegerCacheObject(getCacheKey(username)); if (retryCount == null) { retryCount = 0; } if (retryCount >= Integer.valueOf(maxRetryCount).intValue()) { String errMsg = String.format("密码输入错误%s次,帐户锁定%s分钟", maxRetryCount, lockTime); recordLogService.recordLogininfor(request, user.getUserId().intValue(), username, Constants.LOGIN_FAIL_STATUS,errMsg); throw new ServiceException(errMsg); } if (!matches(user, password)) { retryCount = (int) redisService.incrementCacheValue(getCacheKey(username), lockTime, TimeUnit.MINUTES); redisService.expire(getCacheKey(username), lockTime, TimeUnit.MINUTES); String errMsg = String.format("密码输入错误%s次", retryCount); recordLogService.recordLogininfor(request, user.getUserId().intValue(), username, Constants.LOGIN_FAIL_STATUS, errMsg); if (retryCount >= maxRetryCount) { throw new ServiceException(String.format("密码输入错误%s次,帐户锁定%s分钟", maxRetryCount, lockTime)); } 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)); } } }