我们要实现的就是,密码连续输入错误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的,后续有空我会来测试下这里的代码。

spring boot 实现密码连续输入错误5次,限制十分钟内不能进行登录的更多相关文章

  1. Spring Boot 配置文件密码加密两种方案

    Spring Boot 配置文件密码加密两种方案 jasypt 加解密 jasypt 是一个简单易用的加解密Java库,可以快速集成到 Spring 项目中.可以快速集成到 Spring Boot 项 ...

  2. Spring Boot 揭秘与实战 源码分析 - 开箱即用,内藏玄机

    文章目录 1. 开箱即用,内藏玄机 2. 总结 3. 源代码 Spring Boot提供了很多”开箱即用“的依赖模块,那么,Spring Boot 如何巧妙的做到开箱即用,自动配置的呢? 开箱即用,内 ...

  3. spring boot项目启动报DataSource错误

    初建一个简单的spring boot 项目,启动后会报错. Exception encountered during context initialization - cancelling refre ...

  4. Springboot 系列(七)Spring Boot web 开发之异常错误处理机制剖析

    前言 相信大家在刚开始体验 Springboot 的时候一定会经常碰到这个页面,也就是访问一个不存在的页面的默认返回页面. 如果是其他客户端请求,如接口测试工具,会默认返回JSON数据. { &quo ...

  5. Spring boot 学习笔记 1 - 自定义错误

    Spring Boot提供了WebExceptionHandler一个以合理的方式处理所有错误的方法.它在处理顺序中的位置就在WebFlux提供的处理程序之前,这被认为是最后一个处理程序. 对于机器客 ...

  6. 【spring boot】启动类启动 错误: 找不到或无法加载主类 com.codingapi.tm.TxManagerApplication 的解决方案

    导入的一个外部的spring boot项目,运行启动类,出现错误:找不到或无法加载主类 com.codingapi.tm.TxManagerApplication 解决方案: 将所有错误处理完成后,再 ...

  7. Spring Boot Controller相应JSP页面 错误whitelabel error page

    在学习SpringBoot显示JSP页面的时候出现了错误,Controller可以正常调用,但是JSP页面就是不能正常显示. whitelabel error page 解决:注释掉scope < ...

  8. spring boot 配置https 报这个错误:java.lang.IllegalArgumentException: Private key must be accompanied by certificate chain

    找了接近半天的时间,原来是那么小的问题 server.ssl.key-store=test.jksserver.ssl.key-store-password=123456server.ssl.key- ...

  9. Spring Boot +Vue 项目实战笔记(二):前后端结合测试(登录页面开发)

    前言:关于开发环境 每位 Coder 都有自己偏好的开发工具,从大的方面划分主要有文本编辑器流和 IDE 流两种,我有一段时间也喜欢用编辑器(Sublime Text.Vim),但对我来说开发效率确实 ...

随机推荐

  1. 洗礼灵魂,修炼python(26)--编程核心之“递归”

    递归 1.什么是递归: 其实前面都提过,但没有详细讲.多次调用自身就叫递归 看图,这种就叫递归 看过盗梦空间没?其实也是递归 2.递归需要满足条件: 有调用函数自身 有一个正确的返回条件来结束 在使用 ...

  2. CTR预估中GBDT与LR融合方案

    1. 背景 CTR预估(Click-Through Rate Prediction)是互联网计算广告中的关键环节,预估准确性直接影响公司广告收入.CTR预估中用的最多的模型是LR(Logistic R ...

  3. 用Python做股市数据分析(一)

    本文由 伯乐在线 - 小米云豆粥 翻译.未经许可,禁止转载!英文出处:Curtis Miller.欢迎加入翻译组. 这篇博文是用Python分析股市数据系列两部中的第一部,内容基于我犹他大学 数学39 ...

  4. 遇到电脑IP地址冲突了怎么解决

    由于路由器是自动分配IP地址的,如果多个设备设置的是IP地址自动获取,就会出现IP地址冲突的情况当局域网内有相同IP,并且该机器启动了防火墙,那就没办法自动更新到下一个IP的地址了,所以此时发生了冲突 ...

  5. Java设计模式之五 ----- 外观模式和装饰器模式

    前言 在上一篇中我们学习了结构型模式的适配器模式和桥接模式.本篇则来学习下结构型模式的外观模式和装饰器模式. 外观模式 简介 外观模式隐藏系统的复杂性,并向客户端提供了一个客户端可以访问系统的接口.这 ...

  6. JDK10源码阅读--String

    jdk源码里对String的介绍: String 是不可变的,一旦被创建其值不能被改变. String buffers 支持可变String. 因为String是不可变的, 所以它们可以被共享. 例如 ...

  7. localStorage 知识点

    先补充下localStorage 知识点:JS对象读取形式:localStorage.name添加/修改localStorage.name = "xuanyuan"其中" ...

  8. Postgresql 截取字符串

    截取字符串一般用 substring 就够用了.对于有些长度不定的就没法用这个函数了,但还是有规律的,可以某个字符分割. 如:(这是一个url,截取最后一部分.现在要取 - 后面部分内容) 8a59e ...

  9. 迷宫问题 dfs bfs 搜索

    定义一个二维数组: int maze[5][5] = { 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, ...

  10. df 与 du 已使用空间不一致的原因及解决办法

    通过 df -Th 查看 /var 目录使用了78%, 当登录到/var 目录,du -sh 实际使用112G 分析原因:应该是被删掉的文件 没被真正释放 解决办法: 1.lsof | grep de ...