This commit is contained in:
2026-01-27 15:36:01 +08:00
parent 5bcfadfd85
commit 7890c4d792
5 changed files with 46 additions and 5 deletions

View File

@@ -14,8 +14,8 @@ import com.zhyc.common.utils.SecurityUtils;
import com.zhyc.framework.security.context.AuthenticationContextHolder; import com.zhyc.framework.security.context.AuthenticationContextHolder;
/** /**
* 登录密码方法 * 系统密码服务类,用于处理登录密码验证相关的业务逻辑,包括密码错误次数限制、账户锁定等功能
* *
* @author ruoyi * @author ruoyi
*/ */
@Component @Component
@@ -31,8 +31,8 @@ public class SysPasswordService
private int lockTime; private int lockTime;
/** /**
* 登录账户密码错误次数缓存键名 * 构建登录账户密码错误次数缓存键名
* *
* @param username 用户名 * @param username 用户名
* @return 缓存键key * @return 缓存键key
*/ */
@@ -41,12 +41,21 @@ public class SysPasswordService
return CacheConstants.PWD_ERR_CNT_KEY + username; return CacheConstants.PWD_ERR_CNT_KEY + username;
} }
/**
* 验证用户登录信息,包括密码匹配验证和错误次数限制检查
*
* @param user 待验证的系统用户对象
* @throws UserPasswordRetryLimitExceedException 当密码错误次数超过限制时抛出异常
* @throws UserPasswordNotMatchException 当密码不匹配时抛出异常
*/
public void validate(SysUser user) public void validate(SysUser user)
{ {
// 获取当前认证的用户名和密码
Authentication usernamePasswordAuthenticationToken = AuthenticationContextHolder.getContext(); Authentication usernamePasswordAuthenticationToken = AuthenticationContextHolder.getContext();
String username = usernamePasswordAuthenticationToken.getName(); String username = usernamePasswordAuthenticationToken.getName();
String password = usernamePasswordAuthenticationToken.getCredentials().toString(); String password = usernamePasswordAuthenticationToken.getCredentials().toString();
// 从Redis缓存中获取该用户的密码错误次数
Integer retryCount = redisCache.getCacheObject(getCacheKey(username)); Integer retryCount = redisCache.getCacheObject(getCacheKey(username));
if (retryCount == null) if (retryCount == null)
@@ -54,28 +63,44 @@ public class SysPasswordService
retryCount = 0; retryCount = 0;
} }
// 检查是否达到最大重试次数限制
if (retryCount >= Integer.valueOf(maxRetryCount).intValue()) if (retryCount >= Integer.valueOf(maxRetryCount).intValue())
{ {
throw new UserPasswordRetryLimitExceedException(maxRetryCount, lockTime); throw new UserPasswordRetryLimitExceedException(maxRetryCount, lockTime);
} }
// 验证密码是否匹配
if (!matches(user, password)) if (!matches(user, password))
{ {
// 密码不匹配时,增加错误次数并更新缓存
retryCount = retryCount + 1; retryCount = retryCount + 1;
redisCache.setCacheObject(getCacheKey(username), retryCount, lockTime, TimeUnit.MINUTES); redisCache.setCacheObject(getCacheKey(username), retryCount, lockTime, TimeUnit.MINUTES);
throw new UserPasswordNotMatchException(); throw new UserPasswordNotMatchException();
} }
else else
{ {
// 密码匹配成功,清除登录记录缓存
clearLoginRecordCache(username); clearLoginRecordCache(username);
} }
} }
/**
* 验证原始密码与用户存储密码是否匹配
*
* @param user 系统用户对象
* @param rawPassword 原始密码字符串
* @return 密码匹配返回true否则返回false
*/
public boolean matches(SysUser user, String rawPassword) public boolean matches(SysUser user, String rawPassword)
{ {
return SecurityUtils.matchesPassword(rawPassword, user.getPassword()); return SecurityUtils.matchesPassword(rawPassword, user.getPassword());
} }
/**
* 清除指定登录名的登录记录缓存
*
* @param loginName 登录用户名
*/
public void clearLoginRecordCache(String loginName) public void clearLoginRecordCache(String loginName)
{ {
if (redisCache.hasKey(getCacheKey(loginName))) if (redisCache.hasKey(getCacheKey(loginName)))

View File

@@ -54,7 +54,7 @@ public class UserDetailsServiceImpl implements UserDetailsService
throw new ServiceException(MessageUtils.message("user.blocked")); throw new ServiceException(MessageUtils.message("user.blocked"));
} }
passwordService.validate(user); // passwordService.validate(user);
return createLoginUser(user); return createLoginUser(user);
} }

View File

@@ -38,6 +38,7 @@ public class SwMedicineUsage extends BaseEntity
/** 耳号 */ /** 耳号 */
@Excel(name = "耳号",width = 20, needMerge = true) @Excel(name = "耳号",width = 20, needMerge = true)
private String sheepNo; private String sheepNo;
private String[] sheepNos;
private Integer sheepId; private Integer sheepId;
/** 使用时间 */ /** 使用时间 */
@JsonFormat(pattern = "yyyy-MM-dd") @JsonFormat(pattern = "yyyy-MM-dd")

View File

@@ -46,6 +46,14 @@ public class SwMedicineUsageServiceImpl implements ISwMedicineUsageService
@Override @Override
public List<SwMedicineUsage> selectSwMedicineUsageList(SwMedicineUsage swMedicineUsage) public List<SwMedicineUsage> selectSwMedicineUsageList(SwMedicineUsage swMedicineUsage)
{ {
String[] sheepNos = null;
if (swMedicineUsage.getSheepNo() != null && !swMedicineUsage.getSheepNo().isEmpty()) {
if (swMedicineUsage.getSheepNo().contains(" ")) {
sheepNos = swMedicineUsage.getSheepNo().split(" ");
swMedicineUsage.setSheepNos(sheepNos);
swMedicineUsage.setSheepNo(null);
}
}
return swMedicineUsageMapper.selectSwMedicineUsageList(swMedicineUsage); return swMedicineUsageMapper.selectSwMedicineUsageList(swMedicineUsage);
} }

View File

@@ -73,6 +73,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="sheepNo != null and sheepNo != ''"> <if test="sheepNo != null and sheepNo != ''">
AND bs.manage_tags LIKE CONCAT('%', #{sheepNo}, '%') AND bs.manage_tags LIKE CONCAT('%', #{sheepNo}, '%')
</if> </if>
<if test="sheepNos != null and sheepNos.length > 0">
AND (
<foreach collection="sheepNos" item="item" separator=" OR " open="" close="">
bs.manage_tags LIKE CONCAT('%', #{item}, '%')
</foreach>
)
</if>
<!-- 4. 使用时间区间 --> <!-- 4. 使用时间区间 -->
<if test="params.beginUseTime != null and params.endUseTime != null"> <if test="params.beginUseTime != null and params.endUseTime != null">