package com.test.bijihoudaun.util; import java.time.LocalDateTime; import java.time.temporal.ChronoUnit; import java.util.concurrent.ConcurrentHashMap; /** * 登录锁定工具类 * 使用本地内存存储登录失败记录 */ public class LoginLockUtil { // 最大失败次数 private static final int MAX_FAILED_ATTEMPTS = 5; // 锁定时间(分钟) private static final int LOCK_TIME_MINUTES = 30; // 失败记录过期时间(分钟) private static final int RECORD_EXPIRE_MINUTES = 60; // 登录失败记录:key=用户名,value=失败记录 private static final ConcurrentHashMap attempts = new ConcurrentHashMap<>(); private static class LoginAttempt { int failedCount; LocalDateTime lastAttemptTime; LocalDateTime lockUntil; LoginAttempt() { this.failedCount = 0; this.lastAttemptTime = LocalDateTime.now(); this.lockUntil = null; } } /** * 记录登录失败 * @param username 用户名 */ public static void recordFailedAttempt(String username) { if (username == null || username.isEmpty()) return; cleanupExpiredRecords(); LoginAttempt attempt = attempts.computeIfAbsent(username, k -> new LoginAttempt()); attempt.failedCount++; attempt.lastAttemptTime = LocalDateTime.now(); // 达到最大失败次数,锁定账号 if (attempt.failedCount >= MAX_FAILED_ATTEMPTS) { attempt.lockUntil = LocalDateTime.now().plusMinutes(LOCK_TIME_MINUTES); } } /** * 记录登录成功(清除失败记录) * @param username 用户名 */ public static void recordSuccess(String username) { if (username == null || username.isEmpty()) return; attempts.remove(username); } /** * 检查账号是否被锁定 * @param username 用户名 * @return true-已锁定,false-未锁定 */ public static boolean isLocked(String username) { if (username == null || username.isEmpty()) return false; LoginAttempt attempt = attempts.get(username); if (attempt == null) return false; // 检查是否仍在锁定时间内 if (attempt.lockUntil != null) { if (LocalDateTime.now().isBefore(attempt.lockUntil)) { return true; } else { // 锁定时间已过,清除记录 attempts.remove(username); return false; } } return false; } /** * 获取剩余锁定时间(秒) * @param username 用户名 * @return 剩余秒数,如果未锁定返回0 */ public static long getRemainingLockTime(String username) { if (username == null || username.isEmpty()) return 0; LoginAttempt attempt = attempts.get(username); if (attempt == null || attempt.lockUntil == null) return 0; long remaining = ChronoUnit.SECONDS.between(LocalDateTime.now(), attempt.lockUntil); return Math.max(0, remaining); } /** * 获取剩余失败次数 * @param username 用户名 * @return 剩余次数 */ public static int getRemainingAttempts(String username) { if (username == null || username.isEmpty()) return MAX_FAILED_ATTEMPTS; LoginAttempt attempt = attempts.get(username); if (attempt == null) return MAX_FAILED_ATTEMPTS; return Math.max(0, MAX_FAILED_ATTEMPTS - attempt.failedCount); } /** * 清理过期记录 */ private static void cleanupExpiredRecords() { LocalDateTime now = LocalDateTime.now(); attempts.entrySet().removeIf(entry -> { LoginAttempt attempt = entry.getValue(); // 未锁定且长时间没有登录的记录 if (attempt.lockUntil == null) { return ChronoUnit.MINUTES.between(attempt.lastAttemptTime, now) > RECORD_EXPIRE_MINUTES; } // 锁定已过期的记录 return now.isAfter(attempt.lockUntil); }); } }