本文讲解如何避免“undefined array key 'login_attempts'”错误,通过正确初始化会话变量、实现登录失败计数与账户锁定机制,确保web应用的安全性与健壮性。
在PHP会话($_SESSION)中直接对未定义的键进行递增操作(如 $_SESSION["login_attempts"] += 1)会导致 "Warning: Undefined array key" 错误——因为该键在首次访问前并不存在,PHP无法对 null 执行算术运算。
根本原因在于:你仅在登录失败分支中执行了 $_SESSION["login_attempts"] += 1,但从未预先声明或

✅ 正确做法:在任何读取或修改 $_SESSION["login_attempts"] 前,先确保其存在且为整数类型。推荐在 session_start() 后立即初始化:
此外,原代码中存在几处逻辑隐患,需同步修正:
? 1. 账户锁定判断位置错误
你将锁定检查(if ($_SESSION["login_attempts"] > 2))放在了HTML输出阶段(即表单渲染时),但此时登录逻辑已执行完毕,且未重置计数。这会导致:
✅ 应将锁定逻辑移至登录验证失败后的处理块内,并在锁定后主动终止流程:
if (!isset($_SESSION["user"])) {
if (empty($_POST["user"]) || empty($_POST["password"])) {
$userErr = 'MISSING INPUT!';
$failed = true;
} else {
// ✅ 确保已初始化(上面已做),此处可安全递增
$_SESSION["login_attempts"]++;
// ✅ 在此处检查是否达到阈值并锁定
if ($_SESSION["login_attempts"] >= 3) {
$_SESSION["locked"] = time();
$_SESSION["error"] = "Account locked! Please wait 10 seconds.";
// 清空尝试计数(可选,解锁后会重置)
$_SESSION["login_attempts"] = 0;
} else {
$_SESSION["error"] = "Invalid credentials!";
}
$userErr = 'INVALID CREDENTIALS!';
$failed = true;
}
}当前解锁逻辑仅在每次请求开头检查,但未处理「已锁定但尚未超时」的状态。建议增强:
// 检查是否处于锁定状态且未超时
if (isset($_SESSION["locked"]) && $_SESSION["locked"] > 0) {
$lockedSince = $_SESSION["locked"];
if (time() - $lockedSince <= 10) {
$_SESSION["error"] = "Account still locked. Try again in " . (10 - (time() - $lockedSince)) . " seconds.";
$failed = true;
// 不允许继续登录流程
unset($_SESSION["user"]); // 强制登出(如有)
} else {
// 超时,自动解锁
unset($_SESSION["locked"]);
$_SESSION["login_attempts"] = 0; // 重置计数
}
}通过以上调整,你的登录系统将彻底规避 Undefined array key 错误,并具备可靠的防暴力破解能力。