项目实现“用户多次登录,账号冻结”功能 您所在的位置:网站首页 CA账号密码错误冻结 项目实现“用户多次登录,账号冻结”功能

项目实现“用户多次登录,账号冻结”功能

2024-06-05 17:53| 来源: 网络整理| 查看: 265

博客系统:个人博客系统(Spring Boot、Spring MVC、MyBatis)_拾.柒.的博客-CSDN博客

目录

思路分析

步骤梳理

功能实现

前端操作

后端操作--涉及输错密码次数 state 字段值的查询和修改

思路分析

当用户输入的用户名存在,并且密码输错 3 次以上(包含 3 次),就会触发账号冻结功能。

步骤梳理 首先,对前端传过来的账号和密码进行非空校验,以避免恶意用户使用 Postman 等工具发送非法请求;通过前端传递过来的用户名获取该用户的所有数据,进行非空校验;通过用户表中之前的预留字段 state 对用户输入密码错误次数进行记录,判断 state 的值是否等于 3 ,若等于 3 ,记录当前时间为该用户开始冻结的时间(用 createtime 字段进行记录),然后创建一个线程,使用 wait 进行冻结时间等待,当冻结时间结束,唤醒线程,并将用户输错密码次数修改为 0 ,即 state = 0;若输错密码次数小于 3 次,则进行密码校验,若密码错误则 state + 1,若密码正确则 state = 0;若输错密码次数大于 3 次,则计算剩余冷却时间(剩余冷却时间 = 开始冻结的时间 + 冷冻的时间 - 当前时间),最后将剩余冷却时间反馈给前端(这里要注意时间格式的处理) 功能实现 前端操作

前端相对于之前没有变化,这里功能的实现主要在于后端

后端操作--涉及输错密码次数 state 字段值的查询和修改

若触发账号冻结,将会有一个冻结时间,此处为个人项目,为项目效果展示考虑,设置为 10 s ,在 AppVariable 类里面添加全局变量 FREEZE_TIME = 10;

/** * 全局变量 */ public class AppVariable { //用户session key public static final String USER_SESSION_KEY = "USER_SESSION_KEY"; public static final Integer FREEZE_TIME = 10; }

a. 先实现 mapper.UserMapper( mapper 层)

int getStateByName(@Param("username") String username); int updateStateByName(@Param("username") String username,@Param("sta") Integer sta);

b. 写对应的 xml 实现

select `state` from userinfo where username=#{username} update userinfo set `state`=#{sta} where username=#{username}

c. 实现 service.UserService( service 层代码)

public int getStateByName(String username) { return userMapper.getStateByName(username); } public int updateStateByName(String username, Integer sta) { return userMapper.updateStateByName(username,sta); }

d. 实现 controller.UserController( controller 层)

/** * 登录 */ private Object lock = new Object(); @RequestMapping("/login") public AjaxResult login(HttpServletRequest request, HttpServletResponse response, String username, String password) throws IOException, ParseException, ParseException { //非空校验 if(!StringUtils.hasLength(username) || !StringUtils.hasLength(password)) { return AjaxResult.fail(-1, "账号或密码错误,请稍后重试!"); } //验证用户 Userinfo userinfo = userService.getUserByName(username); if(userinfo == null || !StringUtils.hasLength(userinfo.getUsername()) || !StringUtils.hasLength(userinfo.getPassword())) { return AjaxResult.fail(-2, "账号不存在!"); } //安全校验:当用户输入密码错误 3 次执行冻结(禁止用户登录) SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); if(userService.getStateByName(username) == 3) { //记录该用户开始冻结时间(格式yyyy-MM-ddThh:mm:ss) userinfo.setCreatetime(LocalDateTime.now()); //修改用户开始冻结时间 // userService.updateUserInfoById(userinfo); Thread thread = new Thread(new Runnable() { @Override public void run() { synchronized (lock) { try { //state + 1 userService.updateStateByName(username, userinfo.getState() + 1); lock.wait(AppVariable.FREEZE_TIME); //这里为了演示效果,时间设置为 10s //解冻:修改 state 为 0 userService.updateStateByName(username, 0); lock.notify(); } catch (InterruptedException e) { e.printStackTrace(); } } } }); thread.start(); return AjaxResult.fail(-3, "账号已被冻结,请 10s 后重试!"); } else if(userService.getStateByName(username) > 3) { //账号错误三次以上,计算剩余时间 //将格式话时间转化为时间戳计算 String[] time = userinfo.getCreatetime().toString().split("T"); Date date = simpleDateFormat.parse(time[0] + " " + time[1]); //计算相差秒数(以下计算都是 毫秒级别,因此最后需要除 1000 换算到秒) return AjaxResult.fail(-4, "账号已被冻结,请 "+ ((date.getTime() + AppVariable.FREEZE_TIME - System.currentTimeMillis()) / 1000) +"s 后重试"); } //ps:这里注意要对加盐密码解密 if(userinfo == null || !PasswordUtils.check(password, userinfo.getPassword())) { //用户名不存在或密码错误 if(!PasswordUtils.check(password, userinfo.getPassword())) { //密码错误,该用户的 state 需要 +1 userService.updateStateByName(username, userinfo.getState() + 1); } return AjaxResult.fail(-5, "账号或密码错误,请稍后重试!"); }

以上就是对于“用户多次登录,账号冻结”功能的实现~下次见!



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有