You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP登录表单验证异常:错误场景均返回账户未确认提示

Hey Zac, let's break down why you're getting that misleading "Account not confirmed" error for every login issue—empty fields, wrong password, even non-existent usernames. The problem boils down to how your code flows through checks, plus a couple of PHP type-comparison quirks.

What's Causing the Issue?

  1. Uninterrupted Code Flow: Right now, all your login checks run one after another, even if an error is already set. For example:

    • If someone submits empty fields, you set $error = "Please enter all fields"—but the code keeps running anyway.
    • It then tries to check if the username exists (which it doesn't, or is empty), but still proceeds to the email_active check.
    • When the username doesn't exist, SELECT email_active FROM users WHERE username = :username returns no results. fetchColumn(0) gives false, and in PHP, false == "0" evaluates to true (thanks to loose type comparison). So your code triggers the "Account not confirmed" error, overwriting the original message.
  2. Loose Type Comparisons: Using == instead of === can lead to unexpected matches, like the false == "0" example above.

How to Fix It

We need to make sure that once an error is found, we stop running subsequent checks. We'll also switch to strict comparisons to avoid type-related bugs. Here's the revised code with explanations:

if(isset($_POST['doLogin'])){ 
    $username = $_POST['login-username']; 
    $password = $_POST['login-password']; 
    $error = ''; // Initialize empty error to avoid undefined variable warnings

    // Check for empty fields first
    if(empty($username) || empty($password)){ 
        $error = error("Please enter all fields");
    } 

    // Only run next check if no error exists yet
    if(empty($error)){
        /// Check if username exists
        $SQLCheckLoginn = $odb -> prepare("SELECT COUNT(*) FROM `users` WHERE `username` = :username"); 
        $SQLCheckLoginn -> execute(array(':username' => $username)); 
        $countLoginn = $SQLCheckLoginn -> fetchColumn(0); 
        if ($countLoginn < 1){ 
            $SQL = $odb -> prepare("INSERT INTO `loginlogs` VALUES(:username, :ip, UNIX_TIMESTAMP(), 'XX')"); 
            $SQL -> execute(array(':username' => $username." - does not exist",':ip' => $ip)); 
            $error = error("The username does not exist in our system.");
        }
    }

    // Only check password if username exists and no prior error
    if(empty($error)){
        $SQLCheckLogin = $odb -> prepare("SELECT COUNT(*) FROM `users` WHERE `username` = :username AND `password` = :password"); 
        $SQLCheckLogin -> execute(array(':username' => $username, ':password' => SHA1($password))); 
        $countLogin = $SQLCheckLogin -> fetchColumn(0); 
        // Use strict comparison to ensure we get exactly 1 match
        if (!($countLogin === 1)){ 
            $SQL = $odb -> prepare("INSERT INTO `loginlogs` VALUES(:username, :ip, UNIX_TIMESTAMP(), 'XX')"); 
            $SQL -> execute(array(':username' => $username." - failed login",':ip' => $ip)); 
            $error = error('The password you entered is invalid.');
        }
    }

    // Check ban status only if login credentials are valid
    if(empty($error)){
        $SQL = $odb -> prepare("SELECT `status` FROM `users` WHERE `username` = :username"); 
        $SQL -> execute(array(':username' => $username)); 
        $status = $SQL -> fetchColumn(0); 
        if ($status === 1){ 
            $SQL = $odb -> prepare("SELECT `reason` FROM `bans` WHERE `username` = :username"); 
            $SQL -> execute(array(':username' => $username)); 
            $ban = $SQL -> fetchColumn(0); 
            if(empty($ban)){ 
                $ban = "No reason given."; 
            } 
            $error = error('You are banned. Reason: '.htmlspecialchars($ban));
        }
    }

    // Check email confirmation only if no prior errors
    if(empty($error)){
        $SQL = $odb -> prepare("SELECT `email_active` FROM `users` WHERE `username` = :username"); 
        $SQL -> execute(array(':username' => $username)); 
        $fetch = $SQL -> fetchColumn(0); 
        // Strict comparison to avoid matching false/0 incorrectly
        if ($fetch === "0"){ 
            $error = error('Account not confirmed. Please contact support.');
        }
    }

    // Proceed with login only if no errors
    if(empty($error)){ 
        $SQL = $odb -> prepare("SELECT * FROM `users` WHERE `username` = :username"); 
        $SQL -> execute(array(':username' => $username)); 
        $userInfo = $SQL -> fetch(); 
        $ipcountry = json_decode(file_get_contents("https://www.geoplugin.net/json.gp?ip=".$ip)) -> {'geoplugin_countryName'}; 
        if (empty($ipcountry)) {$ipcountry = 'XX';} 
        $SQL = $odb -> prepare('INSERT INTO `loginlogs` VALUES(:username, :ip, UNIX_TIMESTAMP(), :ipcountry)'); 
        $SQL -> execute(array(':ip' => $ip, ':username' => $username, ':ipcountry' => $ipcountry)); 
        $_SESSION['username'] = $userInfo['username']; 
        $_SESSION['ID'] = $userInfo['ID']; 
        $_SESSION['email'] = $userInfo['email']; 
        setcookie("username", $userInfo['username'], time() + 720000); 
        header('Location: dashboard'); 
        exit; // Stop execution after redirect to prevent unwanted code runs
    } 
}

Key Changes Made:

  • Error-Gated Checks: Each subsequent check is wrapped in if(empty($error)), so we only move forward if no issues were found earlier.
  • Strict Comparisons: Switched from == to === to avoid PHP's loose type matching (e.g., false === "0" will correctly return false).
  • Explicit Error Initialization: Started with $error = '' to avoid undefined variable warnings.
  • Exit After Redirect: Added exit; after header('Location: dashboard'); to ensure no code runs after the redirect.

This way, each error scenario will show its own specific message instead of being overwritten by the "Account not confirmed" error.

内容的提问来源于stack exchange,提问作者Zac Ram

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 08:54:37