SpringBoot整合redis實現(xiàn)輸入密碼錯誤限制登錄功能
需求:
實現(xiàn)一個登錄功能,并且2分鐘之內(nèi)只能輸入5次錯誤密碼,若輸入五次之后還沒有輸入正確密碼,系統(tǒng)將會將該賬號鎖定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 #最大空閑數(shù) maxIdle: 300 #連接池的最大數(shù)據(jù)庫連接數(shù)。設為0表示無限制,如果是jedis 2.4以后用redis.maxTotal #maxActive=600 #控制一個pool可分配多少個jedis實例,用來替換上面的redis.maxActive,如果是jedis 2.4以后用該屬性 maxTotal: 1000 #最大建立連接等待時間。如果超過此時間將接到異常。設為-1表示無限制。 maxWaitMillis: 1000 #連接的最小空閑時間 默認1800000毫秒(30分鐘) minEvictableIdleTimeMillis: 300000 #每次釋放連接的最大數(shù)目,默認3 numTestsPerEvictionRun: 1024 #逐出掃描的時間間隔(毫秒) 如果為負數(shù),則不運行逐出線程, 默認-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 + "超過了限制登錄次數(shù),已被禁止登錄.還剩" + map.get("lockTime") + "分鐘"; } else { //表示沒有被限制登錄 執(zhí)行 下一步登錄邏輯 User user1 = loginService.login(user); //執(zhí)行登錄功能 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分鐘內(nèi) 僅允許輸入錯誤密碼五次,如果超過次數(shù),限制其登錄一小時 * * 給用戶詳細信息提示 * @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")) { //模仿從數(shù)據(jù)庫中根據(jù)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))) { //如果存在就是用戶已經(jīng)輸錯了密碼五次 被鎖定了倆小時 map.put("flag", true); //表示用戶已經(jīng)被鎖定 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; //記錄登錄錯誤次數(shù)的key String key = getMessage.getLoginCountFailKey(user); if (!stringRedisTemplate.hasKey(key)) { //如果不存在 //是第一次登錄失敗 次數(shù)為1 // userlogincountfile;用戶名進行賦值 同時設置失效期2分鐘 stringRedisTemplate.opsForValue().set(key, "1", 2, TimeUnit.MINUTES); return "登錄失敗,在2分鐘內(nèi)還允許輸入錯誤" + (num - 1) + "次"; } else { //如果存在 //查詢登錄失敗次數(shù) long loginFilCount = Long.parseLong(stringRedisTemplate.opsForValue().get(key)); if (loginFilCount < (num - 1)) { //代表當前如果登錄次數(shù)小于4 意思:還有資格繼續(xù)進行登錄 //登錄次數(shù)+1 stringRedisTemplate.opsForValue().increment(key, 1); long secends = stringRedisTemplate.getExpire(key, TimeUnit.SECONDS); //返回的是秒 return user.getUsername() + "登錄失敗,在" + secends + "秒內(nèi)還允許輸入錯誤" + (num - loginFilCount - 1) + "次"; } else { //超過了指定的登錄次數(shù) 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; } }
到此這篇關(guān)于SpringBoot整合redis并實現(xiàn)輸入密碼錯誤限制登錄功能的文章就介紹到這了,更多相關(guān)SpringBoot redis輸入密碼錯誤限制登錄內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Maven添加Tomcat插件實現(xiàn)熱部署代碼實例
這篇文章主要介紹了Maven添加Tomcat插件實現(xiàn)熱部署代碼實例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-04-04淺談Java中浮點型數(shù)據(jù)保留兩位小數(shù)的四種方法
今天在進行開發(fā)的過程中遇到了一個小問題,是關(guān)于如何將double類型的數(shù)據(jù)保留兩位小數(shù)。具有一定的參考價值,本文就詳細的介紹一下2021-09-09如何基于LoadingCache實現(xiàn)Java本地緩存
這篇文章主要介紹了如何基于LoadingCache實現(xiàn)Java本地緩存,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2019-12-12