密码登录失败次数限制,如: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 协议》,转载必须注明作者和本文链接