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超時時間(毫秒),如果不設(shè)置,取默認值2000
timeout: 10000
#最大空閑數(shù)
maxIdle: 300
#連接池的最大數(shù)據(jù)庫連接數(shù)。設(shè)為0表示無限制,如果是jedis 2.4以后用redis.maxTotal
#maxActive=600
#控制一個pool可分配多少個jedis實例,用來替換上面的redis.maxActive,如果是jedis 2.4以后用該屬性
maxTotal: 1000
#最大建立連接等待時間。如果超過此時間將接到異常。設(shè)為-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;用戶名進行賦值 同時設(shè)置失效期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

