MySQL num_rows返回误报

时间:2016-11-15 17:40:33

标签: php mysql

我在下面有这个查询:

// They have a token and estimate id
if (isset($_GET['estimate_token']) && isset($_GET['estimate_id']))
{
    if ($select = $db -> prepare("SELECT estimate_id FROM estimates WHERE estimate_token =?"))
    {
        $select -> bind_param('s', $_GET['estimate_token']);
        $select -> execute();
        $select -> store_result();
        $select -> bind_result($estimate_id);
        $select -> fetch();
        if ($select -> num_rows == '0')
        {
            header ("Location: ./login.php");
        }else{
        }
        $select -> close();
    }
}

通过电子邮件向客户提供带有令牌的链接以及来自数据库的估计ID。当他们点击链接时,它会将它们带到正确的估计值。我遇到的问题是,如果客户手动用网址中的任何数字替换estimate_id或estimate_token,它仍然会让你在网站上将你踢到login.php。这很糟糕,因为它允许客户查看系统中的其他估计值。

我认为问题在于$select -> num_rows抛出误报。

3 个答案:

答案 0 :(得分:1)

您的逻辑无效 - 您必须查找tokenid等于$_GET值的记录,因此您需要使用以下查询:

$SELECT estimate_id FROM estimates WHERE estimate_token =? AND estimate_id = ?

这将只选择一条特定记录。

完整代码类似于:

if ($select = $db -> prepare("SELECT estimate_id FROM estimates WHERE estimate_token = ? and estimate_id = ?"))
{
    // supposing id is `int`
    $select -> bind_param('si', $_GET['estimate_token'], $_GET['estimate_id']);
    $select -> execute();
    $select -> store_result();
    // if you need to know just if row exists
    // there's no need for this two lines
    //$select -> bind_result($estimate_id);
    //$select -> fetch();
    if ($select -> num_rows == 0)
    {
        header ("Location: ./login.php");
    } else {
    }
    $select -> close();
}

答案 1 :(得分:0)

如果他们没有令牌,你不应该立即将他们踢出去吗?我认为这可能是问题所在。或者,按照您编写的方式,如果他们没有令牌和估算ID,您就不会有ELSE。您唯一的ELSE语句位于数据库选择代码中。

答案 2 :(得分:0)

这似乎更合理的逻辑,这将确保他们在提交no或空白令牌/ ID时被拒绝登录。如果您需要进行任何进一步的验证,它也将覆盖您,因为如果您需要将它们丢弃,您只需设置1个bool即可。

由于您未使用数据库中的结果,因此将其更改为数据库端计数可能会稍快一些。

$needsLogin = true;

if (!empty($_GET['estimate_token']) && !empty($_GET['estimate_id']))
{
    $select = $db->prepare('SELECT COUNT(1) FROM estimates WHERE estimate_token = ? AND estimate_id = ?');
    $select->bind_params('si', $_GET['estimate_token'], $_GET['estimate_id']);
    $select->execute();
    $select->bind_result($cnt);
    $select->fetch();
    if ($cnt > 0) {
        $needsLogin = false;
    }
    $select->close();
}

if ($needsLogin) {
    header('Location: ./login.php');
    die();
}

PS。 PDO将使您的数据库代码更好地处理:

$select = $db->prepare('SELECT COUNT(1) FROM estimates WHERE estimate_token = ? AND estimate_id = ?');
$select->execute(array($_GET['estimate_token'], $_GET['estimate_id']));
$cnt = $select->fetchColumn();
if ($cnt > 0) {
    $needsLogin = false;
}