• spring boot 实现密码连续输入错误5次,限制十分钟内不能进行登录


         我们要实现的就是,密码连续输入错误5次,就限制用户十分钟不能进行登录。

         大致的流程图

          

          数据库设计如下

         

    DROP TABLE IF EXISTS `user`;
    CREATE TABLE `user` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `username` varchar(64) NOT NULL COMMENT '用户名',
      `password` varchar(255) NOT NULL COMMENT '用户密码',
      `email` varchar(64) DEFAULT NULL COMMENT '用户邮箱',
      `status` int(11) NOT NULL DEFAULT '0' COMMENT '状态,1代表删除',
      `admin` int(11) NOT NULL DEFAULT '0' COMMENT '是否是管理员,1代表是管理员',
      `iphone` varchar(20) DEFAULT NULL COMMENT '用户手机号',
      `workid` int(11) NOT NULL DEFAULT '0',
      `token` varchar(255) DEFAULT NULL,
      `errornum` int(2) NOT NULL DEFAULT '0',
      `freeze` int(2) NOT NULL DEFAULT '0',
      `freezetime` datetime DEFAULT NULL,
      PRIMARY KEY (`id`,`username`),
      KEY `username` (`username`)
    ) ENGINE=InnoDB AUTO_INCREMENT=49 DEFAULT CHARSET=utf8 COMMENT='用户表';

     那么我们来实现dao层

    package pan.DaoObject;
    
    import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
    import lombok.Data;
    import org.hibernate.annotations.DynamicUpdate;
    import pan.enmus.FreezeEmus;
    import pan.enmus.UserEmus;
    
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.GenerationType;
    import javax.persistence.Id;
    import java.io.Serializable;
    import java.util.Date;
    
    @Data
    @DynamicUpdate
    @Entity
    @JsonIgnoreProperties(value = {"hibernateLazyInitializer", "handler"})
    public class User implements Serializable {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Integer id;
        private String username;
        private String password;
        private String email;
        private String iphone;
        private Integer status = UserEmus.UNDELETE.getCode();
        private Integer admin = UserEmus.NOTADMIN.getCode();
        private String token;
        private Date freezetime;
        private  Integer errornum;
        private  Integer freeze= FreezeEmus.UNDELETE.getCode();
    }

     对应的UserEmus 

    package pan.enmus;
    
    import lombok.Getter;
    
    @Getter
    public enum UserEmus {
        ADMIN(1, "管理员"),
        NOTADMIN(0, "非管理员"),
        DELETE(1, "删除"),
        UNDELETE(0, "正常");
        private Integer code;
        private String message;
    
        UserEmus(Integer code, String message) {
            this.code = code;
            this.message = message;
        }
    }
    FreezeEmus  为:
    package pan.enmus;
    
    import lombok.Getter;
    
    @Getter
    public enum FreezeEmus {
        DELETE(1,"冻结"),
        UNDELETE(0,"正常");
        private Integer code;
        private  String message;
        FreezeEmus(Integer code, String message){
            this.code=code;
            this.message=message;
        }
    }

    那么接下来,我们就是UserRepository实现

    public interface UserRepository extends JpaRepository<User, Integer> {
    User findByUsername(String username);
    }

    里面就用到了一个通过username查找用户

    那么我们接下来去实现service

    @Service
    public class UserSericeImpl {
     @Autowired
        private UserRepository userRepository;
    
    @Override
    public User login(String username, String password) {
    User user = userRepository.findByUsername(username);
    if (user != null) {
    if (user.getStatus().equals( UserEmus.DELETE.getCode())){
    throw new PanExection(ResultEmus.USER_DELETE);
    }
    SimpleDateFormat format=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    try{
    try {
    if(user.getFreeze().equals(FreezeEmus.DELETE.getCode())&& (new Date().getTime()-format.parse(user.getFreezetime().toString()).getTime()<6*60*1000)){
    user.setErrornum(0);
    userRepository.saveAndFlush(user);
    throw new PanExection(ResultEmus.USER_FREE);
    }
    } catch (ParseException e) {
    e.printStackTrace();
    }
    }catch (NullPointerException e){
    userRepository.saveAndFlush(user);
    }
    Boolean b = null;
    try {
    b = MD5Until.checkoutpassword(password, user.getPassword());
    } catch (Exception e) {
    throw new PanExection(ResultEmus.EXCEPTIONS);
    }
    if (b) {
    String key = "Plan_" + user.getUsername();
    String tokned = (String) userredis(redisTemplate).opsForValue().get(key);
    user.setErrornum(0);
    user.setFreezetime(null);
    if (tokned == null) {
    Date date = new Date();
    String tokne = null;
    try {
    tokne = MD5Until.md5(key + date.toString());
    } catch (Exception e) {
    throw new PanExection(ResultEmus.EXCEPTIONS);
    }
    String token = user.getUsername() + "_" + tokne;
    user.setToken(token);
    userRepository.saveAndFlush(user);
    userredis(redisTemplate).opsForValue().set(key, token, 1, TimeUnit.DAYS);
    return user;
    } else {
    userRepository.saveAndFlush(user);
    return user;
    }
    }else {
    if(user.getErrornum()>4){
    user.setErrornum(user.getErrornum()+1);
    user.setFreeze(FreezeEmus.DELETE.getCode());
    user.setFreezetime(new Date());
    userRepository.saveAndFlush(user);
    throw new PanExection(ResultEmus.USER_FREE);
    }else {
    Integer err=user.getErrornum()+1;
    user.setErrornum(err);
    userRepository.saveAndFlush(user);
    throw new PanExection(ResultEmus.USER_ERROR_PASSWORD);
    }
    }
    }
    throw new PanExection(ResultEmus.USER_NOT_EXIT);
    }
    }
    我们最后去实现一个contorller类
    import io.swagger.annotations.Api;
    import io.swagger.annotations.ApiOperation;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.validation.BindingResult;
    import org.springframework.web.bind.annotation.*;
    import pan.DaoObject.User;
    import pan.Form.UserForm;
    import pan.config.RedisConfig;
    import pan.converter.UserForm2User;
    import pan.enmus.ResultEmus;
    import pan.exection.PanExection;
    import pan.service.FileService;
    import pan.service.UserSerice;
    import pan.untils.RedisDbInit;
    import pan.untils.ResultVOUntils;
    import pan.vo.ResultVO;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.validation.Valid;
    import java.util.HashMap;
    import java.util.Map;
    
    @RestController
    @Api(tags = "2.4", description = "登录", value = "实现登录")
    @RequestMapping("/plan")
    public class LoginContorl {
        @Autowired
        private UserSerice userSerice;
        @Autowired
        private RedisTemplate redisTemplate;
        @Autowired
        private FileService fileService;
    
        private RedisTemplate setusertoken(RedisTemplate redisTemplate) {
            redisTemplate = RedisDbInit.initRedis(RedisConfig.userreidport, redisTemplate);
            return redisTemplate;
        }
    
        @ApiOperation(value = "登录", notes = "用户登录")
    
        @PostMapping(value = "/login", produces = "application/json")
        public ResultVO login(@Valid UserForm userForm,
                              BindingResult bindingResult) {
            if (bindingResult.hasErrors()) {
                throw new PanExection(ResultEmus.PARM_ERROR.getCode(), bindingResult.getFieldError().getDefaultMessage());
            }
            User user = UserForm2User.convert(userForm);
            User login = userSerice.login(user.getUsername(), user.getPassword());
            Map<String, String> map = new HashMap<>();
            String redis = (String) setusertoken(redisTemplate).opsForValue().get("Plan_" + user.getUsername());
            Boolean superadmin=userSerice.usersuperadmin(login.getId());
            if(superadmin){
                map.put("is_super","1");
            }else{
                map.put("is_super","0");
            }
            if (login != null) {
                map.put("userid", login.getId().toString());
                map.put("token", redis);
                return ResultVOUntils.success(map);
            }
            return ResultVOUntils.error(1, "密码或者用户名错误");
        }
    }

    到此我们的代码部分已经实现,

    补充  

    ResultVOUntils代码
    public class ResultVOUntils {
        public  static ResultVO success(Object object){
            ResultVO resultVO=new ResultVO();
            resultVO.setData(object);
            resultVO.setMsg("成功");
            resultVO.setCode(0);
            return resultVO;
        }
        public  static ResultVO success(){
          return success(null);
        }
        public  static  ResultVO error(Integer code ,String msg){
            ResultVO resultVO=new ResultVO();
            resultVO.setCode(code);
            resultVO.setMsg(msg);
            return resultVO;
        }
        public  static  ResultVO error(Object object){
            ResultVO resultVO=new ResultVO();
            resultVO.setData(object);
            resultVO.setMsg("失败");
            resultVO.setCode(1);
            return  resultVO;
        }
    }

    restultvo代码

    import lombok.Data;
    
    @Data
    public class ResultVO<T> {
        private Integer code;
        private String msg;
        private T data;
    }
    PanExection代码
    package pan.exection;
    
    import lombok.Getter;
    import pan.enmus.CaseResultEmus;
    import pan.enmus.ResultEmus;
    
    @Getter
    public class PanExection extends RuntimeException {
        private Integer code;
    
        public PanExection(ResultEmus resultEmuns) {
            super(resultEmuns.getMessage());
            this.code = resultEmuns.getCode();
        }
    
        public PanExection(CaseResultEmus resultEmuns) {
            super(resultEmuns.getMessage());
            this.code = resultEmuns.getCode();
        }
    
        public PanExection(Integer code, String message) {
            super(message);
            this.code = code;
        }
    }

    那么到现在我们的代码已经实现 完毕,那么我们去实验下,

    使用数据 lileilei  密码lileilei  进行校验

    使用postman进行测试,密码输入正确返回结果正常

     密码输入错误



    超出后

     补充ResultEmus代码:
    package pan.enmus;
    
    import lombok.Getter;
    
    @Getter
    public enum ResultEmus {
    SUCCESS_REQUEST(0, "成功"),
        USER_NOT_EXIT(1, "用户不存在"),
        USER_BIND(2, "用户已经绑定"),
        USER_DELETE(3, "用户已经删除"),
        EXCEPTIONS(4, "转化异常"),
        USER_ERROR_PASSWORD(225, "密码错误"),
     USER_FREE(115,"你已经被冻结,密码输入次数超过五次,请10分钟再来登录"),
        ;
        private Integer code;
        private String message;
    
        ResultEmus(Integer code, String message) {
            this.code = code;
            this.message = message;
        }
    }
    到这里,我们的登录已经实现完毕。在标准的工程里面可以正常实现,
    由于我配置了阿里的druid的监控
    那么我可以看到相应的监控信息sql执行情况

    这样我们用mysql实现的简单的用户名密码输入错误5次,限制登录十分钟就实现完毕。


    实现起来没有那么难,难的是我们的思路,已经在不断的调试中前进,其实我还是感觉这里面是有bug的,后续有空我会来测试下这里的代码。

  • 相关阅读:
    Data Visualisation Cheet Sheet
    数据预处理
    算法题目
    集成方法
    Mysql数据库重要知识点(知了堂学习心得)
    Working with Data » Getting started with ASP.NET Core and Entity Framework Core using Visual Studio » 创建复杂数据模型
    Working with Data » Getting started with ASP.NET Core and Entity Framework Core using Visual Studio » 排序、筛选、分页以及分组
    Working with Data » 使用Visual Studio开发ASP.NET Core MVC and Entity Framework Core初学者教程
    ASP.NET Core文档中Work with Data章节的翻译目录
    webpages框架中使用Html.TextArea()在前台显示多行信息时,如何进行大小、样式的设置
  • 原文地址:https://www.cnblogs.com/leiziv5/p/10430702.html
Copyright © 2020-2023  润新知