如果提供了合格的令牌,则更新数据库 table 行

Update database table row if a qualifying token is provided

我的代码工作正常,但这是一个有效的代码,就像第 16 行(评论)我想使用 $row 并与上面提到的变量进行比较,而不是编写另一个 SQL查询。

我尝试使用变量和 $row['field name'],但它抛出错误“尝试访问 null 类型值的数组偏移量”。

<?php
require('../private/autoload.php');
if(isset($_GET['token'])){
    $msg ="Email verified successfully, Thankyou.";
    $token = $_GET['token'];
    $email_status = "active";
    $sql = "SELECT `email_token`, `email_status` FROM `users` where `email_token` = ? AND `email_status` = 'inactive' LIMIT 1";
    $stmt = $conn->prepare($sql);
    $stmt->bind_param("s",$token);
    $stmt->execute();
    $result = $stmt->get_result();
    $exist = $result->num_rows;
    if($exist == 0 ){

        // $row = $result->fetch_array(MYSQLI_ASSOC); 
    $sql = "SELECT `email_token`, `email_status` FROM `users` where `email_token` = ? AND `email_status` = ? LIMIT 1";   //Line 16
        $stmt = $conn->prepare($sql);
        $stmt->bind_param("ss",$token,$email_status);
        $stmt->execute();
        $result = $stmt->get_result();
        $exist = $result->num_rows;
        if($exist == 1 ){
        ?>
            <script>
                alert("Email already verified.");
                window.location = "../public/index.php";
            </script>;

        <?php exit(); ?>
        
        <?php }else{ ?>
            <script>
                alert("User not found.");
                window.location = "../public/index.php";
            </script>;
      <?php  } 

    }else{
        $sql = "UPDATE `users` SET `email_status`= ? where `email_token` = ?  LIMIT 1";
        $stmt = $conn->prepare($sql);
        $stmt->bind_param("ss",$email_status,$token);
        $stmt->execute();
        $stmt->close();  
        $_SESSION['msg'] = $msg;
        $_SESSION['token'] = $token;
        header('Location: mobile_verify.php');     
    }
}else{
    header('Location: index.php');
    die();
}
 
$conn->close();
?>

建议是将两者结合起来,减少查询次数。一个用户不能同时处于“活跃”或“不活跃”状态,因此无需进行两次查询。

第一个查询已过时,因为所有信息都包含在第二个查询中。

(请同时阅读初始 post 的评论)

  1. 通常,您不希望从 $_GET 请求对 server-side 执行“写入”过程,但我假设您正在向用户发送电子邮件,他们只是单击一个超链接,所以这是可以容忍的情况。
  2. 我不知道您的令牌的加密安全性如何(UUID 是个好主意),但仅依靠一个数据点可能还不够。您可能希望在有效负载中包含第二个数据点,例如您发送到的 md5() 编码电子邮件,或令牌过期的表达式。这些辅助数据点不需要加密安全,但应避免意外数据冲突或成功的暴力攻击。
  3. 我建议您的回复不要提供有关失败结果的过多细节。提供这些类型的线索对黑客的好处比你想要的要多。

非常简单,执行更新查询,然后根据受影响的行数,在需要的地方重定向。确保在需要维护会话的每个页面的开头启动会话。

未经测试的推荐:

$token = $_GET['token'] ?? null;
if ($token) {
    require('../private/autoload.php');              
    $sql = "UPDATE users
            SET email_status='active'
            WHERE email_status='inactive'
              AND email_token=? LIMIT 1";
    $stmt = $conn->prepare($sql);
    $stmt->bind_param("s", $token);
    $stmt->execute();
    if ($stmt->affected_rows) {
        $_SESSION['msg'] = "Email verified successfully, Thank you.";
        $_SESSION['token'] = $token; // why store this in the session?
        header('Location: mobile_verify.php');
        exit();
    }
}
// missing or invalid submission
header('Location: index.php');
exit();