欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

SpringBoot實現(xiàn)賬號登錄錯誤次數(shù)的限制和鎖定功能

 更新時間:2024年12月02日 11:11:40   作者:小小工匠  
本文介紹了如何使用SpringBoot和Redis實現(xiàn)賬號登錄錯誤次數(shù)限制和鎖定功能,通過自定義注解和AOP切面,結(jié)合配置文件靈活設置最大嘗試次數(shù)和鎖定時長,感興趣的朋友跟隨小編一起看看吧

Pre

SpringBoot - 優(yōu)雅的實現(xiàn)【流控】

需求

需求描述:

  • 登錄錯誤次數(shù)限制:在用戶登錄時,記錄每個賬號的登錄錯誤次數(shù),并限制連續(xù)錯誤的次數(shù)。
  • 賬號鎖定機制:當一個賬號連續(xù)輸入錯誤密碼超過5次時,該賬號將被鎖定15分鐘。在15分鐘后,賬號會自動解鎖。
  • 自動解鎖功能:賬號在連續(xù)錯誤輸入超過5次后,將觸發(fā)鎖定機制,并且5分鐘后自動解鎖,利用Redis的鍵值存儲來管理錯誤次數(shù)和鎖定時間。
  • 配置文件:登錄錯誤次數(shù)的限制(如5次錯誤)和賬號鎖定時間(如15分鐘)應該能通過配置文件進行設置,以便靈活配置。
  • 自定義注解實現(xiàn):使用自定義注解來實現(xiàn)登錄錯誤次數(shù)限制與賬號鎖定功能的邏輯。

技術細節(jié):

  • 使用Redis的Key來存儲和管理每個用戶的錯誤登錄次數(shù)和鎖定狀態(tài)。
  • 自定義注解實現(xiàn)錯誤次數(shù)和鎖定時長的判斷與控制。
  • 錯誤次數(shù)和鎖定時長通過配置文件(如application.ymlapplication.properties)進行配置,支持靈活調(diào)整。

實現(xiàn)步驟

簡易實現(xiàn)

1. 添加依賴

首先,在pom.xml中添加必要的依賴:

 <dependencies>
    <!-- Spring Boot Starter Data Redis -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
    <!-- Spring Boot Starter Web -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- Spring Boot Starter AOP -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-aop</artifactId>
    </dependency>
</dependencies>

2. 配置文件

在application.yml中配置相關參數(shù):

3. 自定義注解

創(chuàng)建一個自定義注解@LoginAttemptLimit:

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface LoginAttemptLimit {
    // 默認值依賴配置文件,可在此處設定默認值
    int maxAttempts() default 5;
    int lockTime() default 15;
}

4. AOP切面

創(chuàng)建一個AOP切面來處理登錄錯誤次數(shù)的限制和鎖定邏輯:

@Aspect
@Slf4j
@Component
public class LoginAttemptLimitAspect {
    @Resource
    private LoginAttemptValidator loginAttemptValidator;
    @Resource
    private AdminAuthService authService;
    @Value("${supervision.max-attempts:2}")
    private int maxAttempts;
    @Value("${supervision.lock-time:5}")
    private long lockTime;
    @Around("@annotation(loginAttemptLimit)")
    public Object limitLoginAttempts(ProceedingJoinPoint joinPoint, LoginAttemptLimit loginAttemptLimit) throws Throwable {
        String attemptKey = "";
        String lockKey = "";
        // 根據(jù)登錄類型獲取對應的鍵
        // # 0 賬號密碼模式  1 key模式(默認)
        if (authService.getLoginType() == 1) {
            AuthKeyLoginReqVO authKeyLoginReqVO = (AuthKeyLoginReqVO) joinPoint.getArgs()[0];
            attemptKey = RedisKeyConstants.ATTEMP_KEY_PREFIX + authKeyLoginReqVO.getUsername();
            lockKey = RedisKeyConstants.LOCK_KEY_PREFIX + authKeyLoginReqVO.getUsername();
        } else {
            AuthLoginReqVO authLoginReqVO = (AuthLoginReqVO) joinPoint.getArgs()[0];
            attemptKey = RedisKeyConstants.ATTEMP_KEY_PREFIX + authLoginReqVO.getUsername();
            lockKey = RedisKeyConstants.LOCK_KEY_PREFIX + authLoginReqVO.getUsername();
        }
        // 檢查賬號是否已被鎖定
        if (loginAttemptValidator.isLocked(lockKey)) {
            throw new ServiceException(TOO_MANY_REQUESTS.getCode(), "賬號被鎖定,請稍后重試");
        }
        // 獲取登錄次數(shù)
        int attempts = loginAttemptValidator.getAttempt(attemptKey);
        // 檢查登錄嘗試次數(shù)是否超過最大限制
        if (attempts >= maxAttempts) {
            loginAttemptValidator.setLock(lockKey, lockTime);
            loginAttemptValidator.resetAttempt(attemptKey);
            throw new ServiceException(TOO_MANY_REQUESTS.getCode(), "賬號被鎖定,請稍后重試");
        }
        try {
            // 執(zhí)行登錄操作
            Object result = joinPoint.proceed();
            // 登錄成功,重置登錄嘗試計數(shù)
            loginAttemptValidator.resetAttempt(attemptKey);
            return result;
        } catch (Exception e) {
            // 登錄失敗,增加登錄嘗試計數(shù)
            loginAttemptValidator.incrementAttempt(attemptKey);
            throw e;
        }
    }
}

5. 使用自定義注解:

在服務的方法上添加自定義注解

6. 測試

創(chuàng)建一個控制器來處理登錄請求

連續(xù)錯誤5次后,

Redis中Key的TTL

import cn.hutool.core.util.ObjectUtil;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;
@Component
public class LoginAttemptValidator {
    @Resource
    private RedisTemplate<String,Integer> redisTemplate;
    /**
     * 嘗試次數(shù)自增
     *
     * @param key Redis中的鍵,用于標識特定的嘗試計數(shù)
     */
    public void incrementAttempt(String key) {
        redisTemplate.opsForValue().increment(key);
    }
    /**
     * 獲取嘗試次數(shù)
     * 如果給定鍵的嘗試次數(shù)在緩存中不存在,則初始化嘗試次數(shù)為0
     * 此方法主要用于跟蹤某些操作的嘗試次數(shù),例如登錄嘗試次數(shù),以防止暴力破解
     *
     * @param key 緩存中的鍵,通常與特定用戶或操作相關聯(lián)
     * @return 嘗試次數(shù)如果緩存中沒有對應的嘗試記錄,則返回0
     */
    public int getAttempt(String key) {
        // 從Redis中獲取嘗試次數(shù)
        Integer attempts = redisTemplate.opsForValue().get(key);
        // 如果嘗試次數(shù)為空,則初始化嘗試次數(shù)
        if (attempts == null ) initAttempt(key);
        // 返回嘗試次數(shù)如果為null,則返回0
        return attempts == null ? 0 : attempts;
    }
    /**
     * 初始化嘗試次數(shù)
     * 該方法用于在Redis中初始化一個鍵的嘗試次數(shù)為0
     * 主要用于記錄和管理操作的嘗試次數(shù),以便進行后續(xù)的限制或監(jiān)控
     *
     * @param key Redis中的鍵,用于唯一標識一個操作或請求
     */
    public void initAttempt(String key) {
        redisTemplate.opsForValue().set(key, 0);
    }
    /**
     * 重置嘗試次數(shù)
     * 通過刪除Redis中的鍵來重置特定嘗試的計數(shù)
     *
     * @param key Redis中用于標識嘗試計數(shù)的鍵
     */
    public void resetAttempt(String key) {
        redisTemplate.delete(key);
    }
    /**
     * 設置緩存鎖
     *
     * @param key 鎖的唯一標識,通常使用業(yè)務鍵作為鎖的key
     * @param duration 鎖的持有時間,單位為分鐘
     *
     * 此方法旨在通過Redis實現(xiàn)分布式鎖的功能,通過設置一個具有過期時間的鍵值對來實現(xiàn)
     * 鍵值對的key為業(yè)務鍵,值為鎖定標志,過期時間由參數(shù)duration指定
     */
    public void setLock(String key, long duration) {
        redisTemplate.opsForValue().set(key, RedisKeyConstants.LOCK_FLAG, duration, TimeUnit.MINUTES);
    }
    /**
     * 檢查給定鍵是否處于鎖定狀態(tài)
     *
     * @param key 要檢查的鍵
     * @return 如果鍵未鎖定,則返回false;如果鍵已鎖定,則返回true
     */
    public boolean isLocked(String key) {
        // 從Redis中獲取鍵對應的值
        Integer value = redisTemplate.opsForValue().get(key);
        // 如果值為空,則表明鍵未鎖定,返回false
        if (ObjectUtil.isEmpty(value)) return  false ;
        // 比較鍵的值是否與鎖定標志相等,如果相等則表明鍵已鎖定,返回true
        return RedisKeyConstants.LOCK_FLAG == redisTemplate.opsForValue().get(key);
    }
}

總結(jié)

基于Spring Boot的賬號登錄錯誤次數(shù)限制和鎖定功能,使用了Redis來存儲登錄失敗次數(shù)和鎖定狀態(tài),并通過自定義注解和AOP來實現(xiàn)切面邏輯。配置文件中可以靈活配置最大嘗試次數(shù)和鎖定時長。

到此這篇關于SpringBoot實現(xiàn)賬號登錄錯誤次數(shù)的限制和鎖定功能的文章就介紹到這了,更多相關SpringBoot賬號登錄錯誤鎖定內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Spring Boot中擴展XML請求與響應的支持詳解

    Spring Boot中擴展XML請求與響應的支持詳解

    這篇文章主要給大家介紹了關于Spring Boot中擴展XML請求與響應的支持的相關資料,文中通過實例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2018-09-09
  • spring在IoC容器中裝配Bean詳解

    spring在IoC容器中裝配Bean詳解

    這篇文章主要介紹了spring在IoC容器中裝配Bean詳解,具有一定借鑒價值,需要的朋友可以參考下
    2017-12-12
  • Spring5+SpringMvc+Hibernate5整合的實現(xiàn)

    Spring5+SpringMvc+Hibernate5整合的實現(xiàn)

    這篇文章主要介紹了Spring5+SpringMvc+Hibernate5整合的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-06-06
  • 詳解Spring如何注入靜態(tài)變量

    詳解Spring如何注入靜態(tài)變量

    這篇文章主要為大家詳細介紹了Spring是如何注入靜態(tài)變量的,文中的示例代碼講解詳細,具有一定的學習價值,感興趣的小伙伴可以了解一下
    2023-06-06
  • Java程序執(zhí)行時間的2種簡單方法

    Java程序執(zhí)行時間的2種簡單方法

    這篇文章介紹了Java程序執(zhí)行時間的2種簡單方法,有需要的朋友可以參考一下
    2013-09-09
  • Java靜態(tài)static與實例instance方法示例

    Java靜態(tài)static與實例instance方法示例

    這篇文章主要為大家介紹了Java靜態(tài)static與實例instance方法示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-08-08
  • springsecurity基于token的認證方式

    springsecurity基于token的認證方式

    本文主要介紹了springsecurity基于token的認證方式,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-08-08
  • spring單元測試之@RunWith的使用詳解

    spring單元測試之@RunWith的使用詳解

    這篇文章主要介紹了spring單元測試之@RunWith的使用詳解,@RunWith 就是一個運行器,@RunWith(JUnit4.class) 就是指用JUnit4來運行,
    @RunWith(SpringJUnit4ClassRunner.class),讓測試運行于Spring測試環(huán)境,需要的朋友可以參考下
    2023-12-12
  • IDEA性能優(yōu)化設置(解決卡頓問題)

    IDEA性能優(yōu)化設置(解決卡頓問題)

    在我們?nèi)粘J褂肐DEA進行開發(fā)時,可能會遇到許多卡頓的瞬間,本文主要介紹了IDEA性能優(yōu)化設置,非常具有實用價值,需要的朋友可以參考下
    2023-05-05
  • Java多線程編程中的兩種常用并發(fā)容器講解

    Java多線程編程中的兩種常用并發(fā)容器講解

    這篇文章主要介紹了Java多線程編程中的兩種常用并發(fā)容器講解,分別是ConcurrentHashMap與ConcurrentHashMap,需要的朋友可以參考下
    2015-12-12

最新評論