SpringBoot整合redis实现输入密码错误限制登录功能
需求:
实现一个登录功能,并且2分钟之内只能输入5次错误密码,若输入五次之后还没有输入正确密码,系统将会将该账号锁定1小时
pom.xml
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!-- jedis 包--> <!-- https://mvnrepository.com/artifact/redis.clients/jedis --> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>3.1.0</version> </dependency> <!--springboot整合redis包--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <!-- <dependency>--> <!-- <groupId>org.springframework.boot</groupId>--> <!-- <artifactId>spring-boot-configuration-processor</artifactId>--> <!-- <optional>true</optional>--> <!-- </dependency>--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> </dependencies>
yml配置
#redis redis: #redis机器ip hostname: 127.0.0.1 #redis端口 port: 6379 #redis密码 password: #redis超时时间(毫秒),如果不设置,取默认值2000 timeout: 10000 #最大空闲数 maxIdle: 300 #连接池的最大数据库连接数。设为0表示无限制,如果是jedis 2.4以后用redis.maxTotal #maxActive=600 #控制一个pool可分配多少个jedis实例,用来替换上面的redis.maxActive,如果是jedis 2.4以后用该属性 maxTotal: 1000 #最大建立连接等待时间。如果超过此时间将接到异常。设为-1表示无限制。 maxWaitMillis: 1000 #连接的最小空闲时间 默认1800000毫秒(30分钟) minEvictableIdleTimeMillis: 300000 #每次释放连接的最大数目,默认3 numTestsPerEvictionRun: 1024 #逐出扫描的时间间隔(毫秒) 如果为负数,则不运行逐出线程, 默认-1 timeBetweenEvictionRunsMillis: 30000 #是否在从池中取出连接前进行检验,如果检验失败,则从池中去除连接并尝试取出另一个 testOnBorrow: true #在空闲时检查有效性, 默认false testWhileIdle: true #redis集群配置 #spring.cluster.nodes=192.168.1.1:7001,192.168.1.1:7002,192.168.1.1:7003,192.168.1.1:7004,192.168.1.1:7005,192.168.1.1:7006 #spring.cluster.max-redirects=3 #哨兵模式 #sentinel.host1=192.168.1.1 #sentinel.port1=26379 #sentinel.host2=192.168.1.2 #sentinel.port2=26379 spring: thymeleaf: cache: false prefix: classpath:/templates/ suffix: .html encoding: UTF-8 mode: HTML5 servlet:
bean层:
package com.springbootandredis.springbootredis.bean; public class User { String username; String password; public User() { } public User(String username, String password) { this.username = username; this.password = password; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }
config 配置类
package com.springbootandredis.springbootredis.config; import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; import java.io.Serializable; @Configuration @AutoConfigureAfter(RedisAutoConfiguration.class) public class RedisConfig { @Bean public RedisTemplate<String, Serializable> redisCacheTemplate(LettuceConnectionFactory redisConnectionFactory) { RedisTemplate<String, Serializable> template = new RedisTemplate<>(); template.setKeySerializer(new StringRedisSerializer()); template.setValueSerializer(new GenericJackson2JsonRedisSerializer()); template.setConnectionFactory(redisConnectionFactory); return template; } }
controller
package com.springbootandredis.springbootredis.controller; import com.springbootandredis.springbootredis.Service.ServiceImpl.GetMessageImpl; import com.springbootandredis.springbootredis.Service.ServiceImpl.LoginServiceImpl; import com.springbootandredis.springbootredis.bean.User; import org.hibernate.validator.constraints.pl.REGON; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import javax.servlet.http.HttpServletRequest; import java.util.Map; @Controller public class userlogin { @Autowired LoginServiceImpl loginService; @Autowired GetMessageImpl getMessage; @ResponseBody @RequestMapping("/login") public String login(HttpServletRequest request) { String username = request.getParameter("username"); String password = request.getParameter("password"); User user = new User(username, password); Map<String, Object> map = loginService.loginUserLock(user); //登录 验证第一层 看用户是否被限制登录 if ((Boolean) map.get("flag")) { //如果为true表示被限制登录 return "登录失败,因" + username + "超过了限制登录次数,已被禁止登录.还剩" + map.get("lockTime") + "分钟"; } else { //表示没有被限制登录 执行 下一步登录逻辑 User user1 = loginService.login(user); //执行登录功能 if (user1 != null) { //表示密码正确 登录成功 /** * 清空对应的所有key */ loginService.DeleteMemory(getMessage.getLoginCountFailKey(user)); loginService.DeleteMemory(getMessage.getLoginTimeLockKey(user)); loginService.DeleteMemory(getMessage.getKeyName(user)); return "登录成功"; } else { //登录不成功 计入登录此时 等逻辑操作 return loginService.loginValdate(user); } } } @RequestMapping("/tologin") public String tologin() { return "login"; } }
service interface
package com.springbootandredis.springbootredis.Service; import com.springbootandredis.springbootredis.bean.User; public interface GetMessage { String getKeyName(User user); String getLoginTimeLockKey(User user); String getLoginCountFailKey(User user); } /************分界线***********************************/ package com.springbootandredis.springbootredis.Service; import com.springbootandredis.springbootredis.bean.User; import java.util.Map; public interface LoginService { /** * 验证用户登录的账号和密码 * @param user * @return */ User login(User user); /** * 用户在2分钟内 仅允许输入错误密码五次,如果超过次数,限制其登录一小时 * * 给用户详细信息提示 * @param user * @return */ String loginValdata(User user); /** * 判断当前的登录用户是否被限制登录 * @param user * @return */ Map<String,Object> loginUserLock(User user); /** * 登录不成功的操作(密码错误) * @param user * @return */ String loginValdate(User user); /** * 删除登录失败所存入的键值对 * @param key * @return */ Boolean DeleteMemory(String key); }
service impl
package com.springbootandredis.springbootredis.Service.ServiceImpl; import com.springbootandredis.springbootredis.Service.GetMessage; import com.springbootandredis.springbootredis.bean.User; import org.springframework.stereotype.Service; @Service public class GetMessageImpl implements GetMessage { @Override public String getKeyName(User user) { return "user:"+user.getUsername(); } @Override public String getLoginTimeLockKey(User user) { return "user:loginTime:lock:"+user.getUsername(); } @Override public String getLoginCountFailKey(User user) { return "user:loginCount:fail:"+user.getUsername(); } } /******************************************分界线*************************************/ package com.springbootandredis.springbootredis.Service.ServiceImpl; import com.springbootandredis.springbootredis.Service.LoginService; import com.springbootandredis.springbootredis.bean.User; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Service; import javax.validation.Valid; import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeUnit; @Service public class LoginServiceImpl implements LoginService { @Autowired GetMessageImpl getMessage; @Autowired StringRedisTemplate stringRedisTemplate; /** * 验证用户是密码是否正确 * * @param user * @return */ @Override public User login(User user) { if (user.getUsername().equals("dlf")) { //模仿从数据库中根据username查询密码 然后验证密码是否正确 if (user.getPassword().equals("dlf")) { return user; } } return null; } @Override public String loginValdata(User user) { return null; } /** * 判断当前登录的用户是否被限制登录 * 查询当前key是否存在,如果存在,就被限制,注意:需要给用户做提示:您当前的用户已被限制,还剩多长时间 * 如果不存在就不被限制 * * @param user * @return */ @Override public Map<String, Object> loginUserLock(User user) { Map<String, Object> map = new HashMap<>(); if (stringRedisTemplate.hasKey(getMessage.getLoginTimeLockKey(user))) { //如果存在就是用户已经输错了密码五次 被锁定了俩小时 map.put("flag", true); //表示用户已经被锁定 map.put("lockTime", stringRedisTemplate.getExpire(getMessage.getLoginTimeLockKey(user), TimeUnit.MINUTES)); //得到被锁定之后还剩下多少时间 以分钟返回 } else { map.put("flag", false); //flag 为false 表示用户没有被限制 } return map; } /** * 登录失败的相应操作(密码错误) * * @param user * @return */ @Override public String loginValdate(User user) { Integer num = 5; //记录登录错误次数的key String key = getMessage.getLoginCountFailKey(user); if (!stringRedisTemplate.hasKey(key)) { //如果不存在 //是第一次登录失败 次数为1 // userlogincountfile;用户名进行赋值 同时设置失效期2分钟 stringRedisTemplate.opsForValue().set(key, "1", 2, TimeUnit.MINUTES); return "登录失败,在2分钟内还允许输入错误" + (num - 1) + "次"; } else { //如果存在 //查询登录失败次数 long loginFilCount = Long.parseLong(stringRedisTemplate.opsForValue().get(key)); if (loginFilCount < (num - 1)) { //代表当前如果登录次数小于4 意思:还有资格继续进行登录 //登录次数+1 stringRedisTemplate.opsForValue().increment(key, 1); long secends = stringRedisTemplate.getExpire(key, TimeUnit.SECONDS); //返回的是秒 return user.getUsername() + "登录失败,在" + secends + "秒内还允许输入错误" + (num - loginFilCount - 1) + "次"; } else { //超过了指定的登录次数 String lockkey = getMessage.getLoginTimeLockKey(user); stringRedisTemplate.opsForValue().set(lockkey, "1", 1, TimeUnit.HOURS); return "因登录失败此时超过" + num + "次,以对其限制登录1小时"; } } } @Override public Boolean DeleteMemory(String key) { try { stringRedisTemplate.delete(key); } catch (Exception e) { return false; } return true; } }
到此这篇关于SpringBoot整合redis并实现输入密码错误限制登录功能的文章就介绍到这了,更多相关SpringBoot redis输入密码错误限制登录内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
Maven一键部署Springboot到Docker仓库为自动化做准备(推荐)
这篇文章主要介绍了Maven一键部署Springboot到Docker仓库,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下2020-07-07Java中IO流的BufferedOutputStream和FileOutputStream对比
这篇文章主要介绍了Java中IO流的BufferedOutputStream和FileOutputStream对比,不带缓冲的操作,每读一个字节就要写入一个字节,由于涉及磁盘的IO操作相比内存的操作要慢很多,所以在读写的字节比较少的情况下,效率比较低,需要的朋友可以参考下2023-07-07spring boot实现超轻量级网关的方法(反向代理、转发)
这篇文章主要介绍了spring boot实现超轻量级网关(反向代理、转发)的相关知识,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下2020-11-11IDEA使用学生邮箱无法注册问题:JetBrains Account connection error: 拒绝连接
这篇文章主要介绍了IDEA使用学生邮箱无法注册问题:JetBrains Account connection error: 拒绝连接,文中通过图文及示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧2020-07-07SWT(JFace) Wizard(Eclipse插件编程必备)
SWT(JFace)小制作:Wizard(Eclipse插件编程必备)2009-06-06
最新评论