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

本文涉及的产品
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
简介: 我们要实现的就是,密码连续输入错误5次,就限制用户十分钟不能进行登录。

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

   

大致的流程图


image.png 

数据库设计如下    


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, "密码或者用户名错误");
    }
}


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

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
1月前
|
缓存 前端开发 Java
【二十八】springboot之通过threadLocal+参数解析器实现同session一样保存当前登录信息的功能
【二十八】springboot之通过threadLocal+参数解析器实现同session一样保存当前登录信息的功能
32 1
|
2月前
|
前端开发 安全 Java
SpringBoot 实现登录验证码(附集成SpringSecurity)
SpringBoot 实现登录验证码(附集成SpringSecurity)
|
2月前
|
XML 安全 Java
SpringSecurity系列(三) Spring Security 表单登录
SpringSecurity系列(三) Spring Security 表单登录
|
21天前
|
Java 测试技术 数据库
基于SpringBoot+HTML实现登录注册功能模块
基于SpringBoot+HTML实现登录注册功能模块
|
3月前
|
前端开发 Java 数据库连接
【Java实战篇】SpringBoot+MyBatis快速实现登录注册
【1月更文挑战第19天】【Java实战篇】SpringBoot+MyBatis快速实现登录注册
|
1月前
|
前端开发 JavaScript Java
springboot 集成easy-captcha实现图像验证码显示和登录
springboot 集成easy-captcha实现图像验证码显示和登录
139 0
|
1月前
|
存储 NoSQL 前端开发
【SpringBoot】Redis集中管理Session和自定义用户参数解决登录状态及校验问题
【SpringBoot】Redis集中管理Session和自定义用户参数解决登录状态及校验问题
|
1月前
|
算法 前端开发 JavaScript
SpringBoot+随机盐值+双重MD5实现加密登录
SpringBoot+随机盐值+双重MD5实现加密登录
191 1
|
1月前
|
缓存 前端开发 Java
spring boot3登录开发-3(账密登录逻辑实现)
spring boot3登录开发-3(账密登录逻辑实现)
51 1
|
1月前
|
存储 JSON Java
spring boot3登录开发-1(整合jwt)
spring boot3登录开发-1(整合jwt)
56 1