checkBruteForce($emp_no); if ($lockError) { $error = $lockError; } else { $employee = new Employee(); $user = $employee->validateLogin($emp_no, $password); if ($user) { // 登录成功 — 清除失败记录 $this->clearLoginAttempts($emp_no); // 重新生成 Session ID 防止会话固定攻击 session_regenerate_id(true); $_SESSION['user_id'] = $user['id']; $_SESSION['emp_no'] = $user['emp_no']; $_SESSION['emp_name'] = $user['emp_name']; $_SESSION['role'] = $user['role']; $_SESSION['category'] = $user['category'] ?? self::CATEGORY_MES; // 根据角色和类目跳转到不同页面 if ($user['role'] === self::ROLE_SUPER_ADMIN) { // 超级管理员:默认进入 MES 后台,可通过顶部切换类目 header('Location: ' . BASE_URL . '/Admin/index'); } elseif ($user['role'] === self::ROLE_ADMIN) { // 管理员:根据分配的类目跳转到对应管理界面 $cat = $user['category'] ?? self::CATEGORY_MES; $homeRoute = self::CATEGORY_HOME[$cat] ?? 'Admin/index'; header('Location: ' . BASE_URL . '/' . $homeRoute); } else { // 操作员:进入前台工位界面 header('Location: ' . BASE_URL . '/Front/index'); } exit; } else { // 记录失败 $this->recordLoginAttempt($emp_no); $remaining = $this->getRemainingAttempts($emp_no); // 诊断日志:validateLogin 返回 false(详细日志已在 Employee 中记录) $ua = isset($_SERVER['HTTP_USER_AGENT']) ? substr($_SERVER['HTTP_USER_AGENT'], 0, 150) : 'unknown'; $sess = session_id() ? hash('sha256', session_id()) : 'none'; error_log("[LOGIN_DIAG] RESULT=FAIL emp_no_len=" . strlen($emp_no) . " remaining={$remaining} ua={$ua} sess_hash={$sess}"); $error = '员工编号或密码错误' . ($remaining > 0 ? "(还可尝试 {$remaining} 次)" : '(账号已临时锁定)'); } } } } $this->assign('title', 'MES 系统登录'); $this->assign('error', $error); $this->assign('csrf_token', $this->csrfToken()); $this->render(); } /** * 检查暴力破解状态 */ private function checkBruteForce($emp_no) { $key = 'login_attempts_' . md5($emp_no); $attempts = $_SESSION[$key] ?? []; // 清理过期记录 $now = time(); $attempts = array_filter($attempts, function($t) use ($now) { return $t > ($now - self::ATTEMPT_WINDOW); }); if (count($attempts) >= self::MAX_LOGIN_ATTEMPTS) { $lastAttempt = max($attempts); $waitTime = self::LOCKOUT_DURATION - ($now - $lastAttempt); if ($waitTime > 0) { $minutes = ceil($waitTime / 60); return "登录尝试次数过多,请 {$minutes} 分钟后再试"; } // 锁定时间已过,清除记录 unset($_SESSION[$key]); return null; } $_SESSION[$key] = array_values($attempts); return null; } /** * 记录失败登录尝试 */ private function recordLoginAttempt($emp_no) { $key = 'login_attempts_' . md5($emp_no); $attempts = $_SESSION[$key] ?? []; $now = time(); $attempts = array_filter($attempts, function($t) use ($now) { return $t > ($now - self::ATTEMPT_WINDOW); }); $attempts[] = $now; $_SESSION[$key] = array_values($attempts); } /** * 清除登录尝试记录 */ private function clearLoginAttempts($emp_no) { $key = 'login_attempts_' . md5($emp_no); unset($_SESSION[$key]); } /** * 获取剩余尝试次数 */ private function getRemainingAttempts($emp_no) { $key = 'login_attempts_' . md5($emp_no); $attempts = $_SESSION[$key] ?? []; return max(0, self::MAX_LOGIN_ATTEMPTS - count($attempts)); } public function logout() { session_destroy(); header('Location: ' . BASE_URL . '/'); exit; } }