深入解析:基于若依前后分离版-用户密码错误锁定
sys_config配置参数
user.password.maxRetryCount:最大错误次数
user.password.lockTime:锁定时长
//SysLoginController //登录@PostMapping("/login")public AjaxResult login(@RequestBody LoginBody loginBody){ AjaxResult ajax = AjaxResult.success(); // 生成令牌 String token = sysPasswordService.validate(loginBody, loginService); ajax.put(Constants.TOKEN, token); return ajax;}//解锁@PostMapping("/unlock")public AjaxResult unlock(String loginName) { AjaxResult ajax = AjaxResult.success(); sysPasswordService.clearLoginRecordCache(loginName); return ajax;}
package com.ruoyi.web.controller.system.service; import com.ruoyi.common.constant.Constants;import com.ruoyi.common.core.domain.entity.SysUser;import com.ruoyi.common.core.domain.model.LoginBody;import com.ruoyi.common.exception.ServiceException;import com.ruoyi.common.exception.user.UserPasswordNotMatchException;import com.ruoyi.common.utils.MessageUtils;import com.ruoyi.common.utils.SecurityUtils;import com.ruoyi.framework.manager.AsyncManager;import com.ruoyi.framework.manager.factory.AsyncFactory;import com.ruoyi.framework.web.service.SysLoginService;import com.ruoyi.system.service.ISysConfigService;import org.apache.commons.lang3.StringUtils;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.stereotype.Component; import java.util.Base64;import java.util.concurrent.TimeUnit; @Componentpublic class LockService { public static final String LOGINRECORDCACHE = "loginRecordCache"; @Autowired private RedisTemplate redisTemplate; @Autowired private ISysConfigService configService; public String validate(LoginBody loginBody, SysLoginService loginService) { String loginName = loginBody.getUsername(); String maxRetryCount = configService.selectConfigByKey("user.password.maxRetryCount"); Long fz = Long.parseLong(configService.selectConfigByKey("user.password.lockTime")); Integer retryCount = (Integer)redisTemplate.opsForValue().get(LOGINRECORDCACHE + loginName); if (retryCount == null) { retryCount = new Integer (0); } if (StringUtils.isNotBlank(maxRetryCount)) { retryCount++; if (retryCount > Integer.parseInt(maxRetryCount)) { AsyncManager.me().execute(AsyncFactory.recordLogininfor(loginName, Constants.LOGIN_FAIL, MessageUtils.message("user.password.retry.limit.exceed", maxRetryCount, fz))); throw new ServiceException("重试次数超过限制:" + Integer.parseInt(maxRetryCount)+"次,请"+fz+"分钟后重试"); } } // 生成令牌 try { String token = loginService.login(base64Decode(loginBody.getUsername()), base64Decode(loginBody.getPassword()), loginBody.getCode(), loginBody.getUuid()); clearLoginRecordCache(loginName); return token; } catch (Exception e){ redisTemplate.opsForValue().set(LOGINRECORDCACHE + loginName, retryCount, fz, TimeUnit.MINUTES); AsyncManager.me().execute(AsyncFactory.recordLogininfor(loginName, Constants.LOGIN_FAIL, MessageUtils.message("user.password.retry.limit.count", retryCount))); throw e; } } private final String base64Decode(String base64EncodedString){ // 获取Base64解码器 Base64.Decoder decoder = Base64.getDecoder(); // 解码Base64字符串 byte[] decodedBytes = decoder.decode(base64EncodedString); // 将解码后的字节数组转换为字符串(假设原始数据是文本) return new String(decodedBytes); } public void clearLoginRecordCache(String loginName) { redisTemplate.delete(LOGINRECORDCACHE + loginName); } }