springboot实现密码过期,以及存储5次密码,第六次密码不能与前五次相同

增加是否启用密码过期配置 application.yml

#密码有效期开关
passwordExpire: true
#密码剩余天数提醒修改密码

passwordExpireTip: '#{3*24*60*60}'

1.已存在用户,第一次登录时判断是否存在redis密码过期设置和存储密码list,不存在,则生成redis信息,不存在,跳过。

代码示例:

@Value(value = "${hhxxweb.passwordExpire}")
private boolean passwordExpire;

@PostMapping("/login")
@ResponseBody
public AjaxResult ajaxLogin(HttpServletRequest request,String username, String password, Boolean rememberMe)
{
	try {
		String id = request.getSession().getId();
		byte[] aesKey = StringUtils.hexToByteArray(RedisTool.get(String.format(Constants.LOGIN_AES_KEY, id), String.class));
		if (ArrayUtil.isEmpty(aesKey)){
			return error("登录超时,请刷新页面重试");
		}
		username = Md5Utils.decryptAESCtr(StringUtils.hexToByteArray(username), aesKey);
		password = Md5Utils.decryptAESCtr(StringUtils.hexToByteArray(password), aesKey);
		if(passwordExpire) {
			if(!"zlxt_admin".equals(username)) {
				passwordExpire(username, password);
				String redisPassword = redisCache.getCacheObject("password:expire:" + username);
				if(StringUtils.isEmpty(redisPassword)) {
					String msg = "密码已过期,请联系管理员修改!";
					return error(msg);
				}
			}
		}
		passwordService.validateByUsername(username, password);
	} catch (Exception ex) {
		String msg = "用户或密码错误";
		if (StringUtils.isNotEmpty(ex.getMessage()))
		{
			msg = ex.getMessage();
		}
		return error(msg);
	}
	UsernamePasswordToken token = new UsernamePasswordToken(username, password, rememberMe);
	Subject subject = SecurityUtils.getSubject();
	try
	{
		subject.login(token);
		Long deptId = ShiroUtils.getSysUser().getDeptId();
		return success(String.valueOf(deptId));
	}
	catch (AuthenticationException e)
	{
		String msg = "用户或密码错误";
		if (StringUtils.isNotEmpty(e.getMessage()))
		{
			msg = e.getMessage();
		}
		return error(msg);
	}
}

private void passwordExpire(String username, String password) {
	List<Object> cacheList = redisCache.getCacheList("password:list:" + username);
	if(StringUtils.isEmpty(cacheList)) {
		redisCache.setCacheObject("password:expire:" + username, password, 180, TimeUnit.DAYS);
		List<String> list = new LinkedList<String>();
		list.add(password);
		redisCache.setCacheList("password:list:" + username, list);
	}
}

2.新增用户时,redis密码过期设置和存储密码list增加

@Value(value = "${hhxxweb.passwordExpire}")
private boolean passwordExpire;

/**
 * 新增保存用户信息
 * 
 * @param user 用户信息
 * @return 结果
 */
@Override
@Transactional
public int insertUser(User user)
{
	if(passwordExpire) {
		redisCache.setCacheObject("password:expire:" + user.getLoginName(), user.getPassword(), 180, TimeUnit.DAYS);
		List<String> list = new LinkedList<String>();
		list.add(user.getPassword());
		redisCache.setCacheList("password:list:" + user.getLoginName(), list);
	}
	user.randomSalt();
	user.setPassword(passwordService.encryptPassword(user.getLoginName(), user.getPassword(), user.getSalt()));
	user.setCreateBy(ShiroUtils.getLoginName());
	// 新增用户信息
	int rows = userMapper.insertUser(user);
	// 新增用户岗位关联
	insertUserPost(user);
	// 新增用户与角色管理
	insertUserRole(user.getUserId(), user.getRoleIds());
	return rows;
}

3,重置用户密码时,刷新密码过期机制,重新恢复180天,并且判断密码list存储是否等于5个,如果等于,判断是否和前5次存在相同,存在相同,则抛出异常,不存在时,在重置密码实现类中删除最早的密码,保存新密码,重新生成redis的密码list。

@RequiresPermissions("system:user:resetPwd")
@Log(title = "重置密码", businessType = BusinessType.UPDATE)
@PostMapping("/resetPwd")
@ResponseBody
public AjaxResult resetPwdSave(User user)
{
	userService.checkUserAllowed(user);
	if(passwordExpire) {
		List<String> cacheList = redisCache.getCacheList("password:list:" + user.getLoginName());
		if(cacheList.size() == 5) {
			boolean anyMatch = cacheList.stream().anyMatch(e -> user.getPassword().equals(e));
			if(anyMatch) {
				return error("新密码与前五次密码出现相同,请重新设置密码!");
			}
		}
	}
	if(user.getPassword().contains(user.getLoginName())){
		return error("密码不能包含登录名称!");
	}
	if(!userService.checkPassword(user.getPassword())){
		if (strength){
			return error("密码需包含数字、大写字母、小写字母、特殊字符!");
		}else {
			return error("密码需包含数字和字母");
		}
	}
	if (userService.resetUserPwd(user) > 0)
	{
		if (ShiroUtils.getUserId().longValue() == user.getUserId().longValue())
		{
			setSysUser(userService.selectUserById(user.getUserId()));
		}
		return success();
	}
	return error();
}

接口实现类:

/**
 * 修改用户密码
 * 
 * @param user 用户信息
 * @return 结果
 */
@Override
public int resetUserPwd(User user)
{
	String username = user.getLoginName();
	redisCache.setCacheObject("password:expire:" + username, user.getPassword(), 180, TimeUnit.DAYS);
	List<String> cacheList = redisCache.getCacheList("password:list:" + username);
	if(cacheList.size() == 5) {
		cacheList = cacheList.stream().skip(1).collect(Collectors.toList());
	}
	cacheList.add(user.getPassword());
	redisCache.deleteObject("password:list:" + username);
	redisCache.setCacheList("password:list:" + username, cacheList);
	user.randomSalt();
	user.setPassword(passwordService.encryptPassword(username, user.getPassword(), user.getSalt()));
	return updateUserInfo(user);
}

4.删除用户时,清除缓存

/**
 * 通过用户ID删除用户
 * 
 * @param userId 用户ID
 * @return 结果
 */
@Override
@Transactional
public int deleteUserById(Long userId)
{
	User selectUserById = userMapper.selectUserById(userId);
	redisCache.deleteObject("password:list:" + selectUserById.getLoginName());
	redisCache.deleteObject("password:expire:" + selectUserById.getLoginName());
	// 删除用户与角色关联
	userRoleMapper.deleteUserRoleByUserId(userId);
	// 删除用户与岗位表
	userPostMapper.deleteUserPostByUserId(userId);
	return userMapper.deleteUserById(userId);
}

5.登录成功进入首页时判断密码过期时间是否小于三天,小于三天提示修改密码。

@Value(value = "${hhxxweb.passwordExpire}")
private boolean passwordExpire;

@Value(value = "${hhxxweb.passwordExpireTip}")
private String passwordExpireTip;


boolean isRestPwd = false;
if(passwordExpire) {
	if(!"zlxt_admin".equals(user.getLoginName())) {
		Long expire = redisTemplate.getExpire("password:expire:" + user.getLoginName());
		if(expire < Long.valueOf(passwordExpireTip)) {
			long days = TimeUnit.SECONDS.toDays(expire);
			long hours = TimeUnit.SECONDS.toHours(expire) - TimeUnit.DAYS.toHours(days);
			isRestPwd = true;
			mmap.put("timeTip", "密码还有" + days + "天" + hours + "小时到期,点击确定修改密码!");
		}
	}
}
mmap.put("isRestPwd", isRestPwd);

6.前端部分代码

var isRestPwd = [[${isRestPwd}]] || false;
if(isRestPwd) {
  $.modal.confirm(timeTip, function() {
  	resetPwd();
  });
}
/* 用户管理-重置密码 */
function resetPwd() {
    var url = ctx + 'system/user/profile/resetPwd';
    $.modal.open("重置密码", url, '770', '380');
}

相关推荐

  1. Superset二开发之重置密码

    2024-03-19 20:58:05       5 阅读
  2. 作业

    2024-03-19 20:58:05       20 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-03-19 20:58:05       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-03-19 20:58:05       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-03-19 20:58:05       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-03-19 20:58:05       20 阅读

热门阅读

  1. 在Swift中集成Socket.IO进行实时通信

    2024-03-19 20:58:05       22 阅读
  2. 【NLP11-迁移学习】

    2024-03-19 20:58:05       19 阅读
  3. Jenkins: 搭建Jenkins服务,调通Webhook链路

    2024-03-19 20:58:05       22 阅读
  4. LlamaParse: 高效的PDF文件RAG解析工具

    2024-03-19 20:58:05       19 阅读
  5. 强缓存和协商缓存的区别

    2024-03-19 20:58:05       20 阅读