这是准备好的陈述吗?

时间:2019-03-13 16:55:02

标签: php html mysql pdo

这是我的代码。

function login($username,$password){
    global $db;
    
    $sql = "SELECT * FROM users133 WHERE username=:username";
    $stmt = $db->prepare($sql);
    $stmt->execute(array(':username' => $username));
    if ($stmt->rowCount() > 0){
        $result = $stmt->fetchAll();
        $hash = $result[0]['password'];
        if (password_verify($password, $hash)) {
            $_SESSION['loggedIn'] = $result[0]['id'];
        header("location: ?page=profile"); /*<----AFTER LOGING IN YOU GET TO THIS PAGE*/
        }else{
            header("location: ?page=loginfailed");
        }
        
    }
    else{
        header("location: ?page=loginfailed");
    }
}

是的,我知道该帖子是重复的,但是还有其他问题我需要问!!今天我花了大约6个小时来阅读如何做准备好的陈述。我读到有关$ stmt-> bindParam命令的信息,该命令使数据库检查输入的值是否为int,string等(以防用户使用检阅元素选项或以表格形式放置恶意代码)。 SELECT准备好的语句是否有必要?我打算从此登录功能复制代码,并在我的网站的其他地方使用它。这就是为什么我需要询问它是否以目前的方式是100%安全的。

1 个答案:

答案 0 :(得分:4)

是的,您正在使用带有参数的预备语句。那是正确的事情。在大多数情况下,参数是编写安全SQL语句的最佳方法。在极少数情况下它们无济于事(请参阅我对how safe are PDO prepared statements的回答)

根据我的代码编写方式,我可以建议一些小的更改。

$sql = "SELECT id, password FROM users133 WHERE username=:username";

避免使用SELECT *,请始终明确拼写您的列。见

$stmt = $db->prepare($sql);
$stmt->execute(['username' => $username]);

如果启用了PDO异常,则可以,因为任何SQL错误都会中断代码并引发异常。但是,如果未启用例外,则应始终检查prepare()execute()的返回值。参见http://php.net/manual/en/pdo.error-handling.phphttp://php.net/manual/en/pdo.errorinfo.php

array()的语法来自旧的PHP版本,并且自PHP 5.4起,您可以在方括号中使用较短的语法。

您不需要在PDO参数的密钥中使用:。仅在SQL字符串中。在旧版本的PDO中,两个地方都需要:,但现在不再需要。

while (row = $stmt->fetch()) {
    $hash = $row['password'];
    if (password_verify($password, $hash)) {
        $_SESSION['loggedIn'] = $row['id'];
        header("location: ?page=profile");
    }else{
        header("location: ?page=loginfailed");
    }
}
header("location: ?page=loginfailed");

以上内容避免了调用rowCount()。如果没有行,则while()自然会不做任何循环就结束,然后进入最后的header()调用。

我宁愿避免调用rowCount(),因为记住它何时有效以及何时无效都令人困惑。在客户端从MySQL服务器获取所有行之前,rowCount()将返回0。有时,执行查询会隐式地将所有行提取到客户端内存中,然后调用fetch()只是对其进行迭代。这称为缓冲查询。但是,如果您的结果将有太多行要缓冲,则非缓冲查询很有用。因此,并不总是清楚rowCount()何时会返回准确的计数。