密码登录失败次数限制,如:5分钟内登录失败6次,即锁定账户1小时

package com.guahao.weic.sys.utils;


import java.time.Duration;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

//密码登录失败次数限制,如:5分钟内登录失败6次,即锁定账户1小时
public class AccountLockUtil {

    private static final int MAX_LOGIN_ATTEMPTS = 6; //五分钟内最多登录失败六次
    private static final long LOCK_TIME_IN_MILLISECONDS = 3600000; // 1小时
    private static final long LOCK_RESET_TIME_IN_MILLISECONDS = 300000; // 5分钟

    private static Map<String, AccountInfo> lockedAccounts = new HashMap<>();

    public static synchronized boolean isAccountLocked(String username) {
        AccountInfo accountInfo = lockedAccounts.get(username);
        if (accountInfo == null) {
            return false;
        }
        long lockStartTime = accountInfo.getLockStartTime();
        long currentTime = System.currentTimeMillis();
        // 如果锁定时间已经过去了,重置锁定信息
        if (currentTime - lockStartTime >= LOCK_TIME_IN_MILLISECONDS) {
            lockedAccounts.remove(username);
            return false;
        }
        return true; // 账户仍然被锁定
    }

    public static synchronized void handleFailedLogin(String username) {
        AccountInfo accountInfo = lockedAccounts.get(username);
        if (accountInfo == null) {
            accountInfo = new AccountInfo();
            lockedAccounts.put(username, accountInfo);
        }
        long currentTime = System.currentTimeMillis();
        if (currentTime - accountInfo.getLastAttemptTime() > LOCK_RESET_TIME_IN_MILLISECONDS) {
            accountInfo.resetFailedAttempts(currentTime);
        }
        accountInfo.incrementFailedAttempts();
        if (accountInfo.getFailedAttempts() >= MAX_LOGIN_ATTEMPTS) {
            accountInfo.setLockStartTime(currentTime);
        }
    }

    public static synchronized void handleSuccessfulLogin(String username) {
        lockedAccounts.remove(username);
    }

    private static class AccountInfo {
        private int failedAttempts;
        private long lockStartTime;
        private long lastAttemptTime;

        public int getFailedAttempts() {
            return failedAttempts;
        }

        public void incrementFailedAttempts() {
            failedAttempts++;
        }

        public void resetFailedAttempts(long currentTime) {
            failedAttempts = 0;
            lastAttemptTime = currentTime;
        }

        public long getLockStartTime() {
            return lockStartTime;
        }

        public void setLockStartTime(long lockStartTime) {
            this.lockStartTime = lockStartTime;
            failedAttempts = 0;
        }

        public long getLastAttemptTime() {
            return lastAttemptTime;
        }
    }

}

登录校验示例代码

        try {
            //判断账户是否锁定
            boolean isLock = AccountLockUtil.isAccountLocked(username);
            if ( isLock ) {
                throw new WeicException("账号被锁定,请一小时之后重试");
            } else {
                subject.login(passwordToken);
                AccountLockUtil.handleSuccessfulLogin(username);
            }
        } catch (AuthenticationException e) {
            //记录用户登录失败次数,5分钟内登录失败6次,即锁定账户1小时
            AccountLockUtil.handleFailedLogin(username);
            logger.error("orgLogin登录错误。用户名{},密码{}", authUser.getUsername(), authUser.getPassword());
            throw new WeicException("账号或密码错误");
        }

上述方案在部分复杂环境中无法生效,下面提供第二种方案:

package com.guahao.weic.sys.utils;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;

public class AccountsLockUtil {
    private static Map<String, Integer> failedLoginAttempts = new HashMap<>();
    private static final int MAX_FAILED_ATTEMPTS = 6;
    private static final long LOCKOUT_TIME = 60 * 60 * 1000; // 1 hour in milliseconds


    public static void processFailedLogin(HttpServletRequest request, HttpServletResponse response, String username) {
        int failedAttempts = 1;
        if (failedLoginAttempts.containsKey(username)) {
            failedAttempts = failedLoginAttempts.get(username) + 1;
        }
        failedLoginAttempts.put(username, failedAttempts);

        if (failedAttempts >= MAX_FAILED_ATTEMPTS) {
            Cookie lockoutCookie = new Cookie("lockout", "true");
            lockoutCookie.setMaxAge((int) (LOCKOUT_TIME / 1000)); // set the cookie to expire in 1 hour
            response.addCookie(lockoutCookie);
        }
    }

    //判断账户是否被锁定
    public static boolean isLockedOut(HttpServletRequest request, String username) {
        Cookie[] cookies = request.getCookies();
        if (cookies != null) {
            for (Cookie cookie : cookies) {
                if (cookie.getName().equals("lockout") && cookie.getValue().equals("true")) {
                    return true;
                }
            }
        }
        return false;
    }
}

控制器中代码如下:

        try {
            //判断账户是否锁定
            boolean isLock = AccountsLockUtil.isLockedOut(request,username);
            logger.info("账户状态 {}",isLock);
            if ( isLock ) {
                throw new WeicException("账号被锁定,请一小时之后重试");
            } else {
                subject.login(passwordToken);
            }
        } catch (AuthenticationException e) {
            //记录用户登录失败次数,5分钟内登录失败6次,即锁定账户1小时
            AccountsLockUtil.processFailedLogin(request,response,username);
            logger.info("账户姓名 {}",username);
            logger.error("orgLogin登录错误。用户名{},密码{}", username, password);
            throw new WeicException("账号或密码错误");
        }
本作品采用《CC 协议》,转载必须注明作者和本文链接
写这些文章的初衷只是记录一下自己的学习过程,避免自己忘记
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!