【问题标题】:Is this prepared statement?这是准备好的声明吗?
【发布时间】:2019-08-04 10:51:38
【问题描述】:

这是我的代码。

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% 安全。

【问题讨论】:

标签: php html mysql pdo


【解决方案1】:

是的,您正在使用带有参数的准备好的语句。这是正确的做法。在大多数情况下,参数是编写安全 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() 何时返回准确计数并不总是很清楚。

【讨论】:

  • 非常感谢您抽出宝贵时间。老实说,你的版本对我来说似乎有点复杂。我什至从未使用过“while”命令。我会继续我自己的方式。再次感谢您的时间。是的 PDO 例外已启用。
  • 在这种情况下,由于您只寻找一个结果,您可以使用“if”而不是“while”。 while 语句的参数很重要。它同时做两件事:它获取下一行,但如果该行不存在,则条件失败。这是一个非常有用的做法,值得学习。更不用说它避免了 rowCount 可能带来的心痛。
猜你喜欢
  • 2013-10-11
  • 1970-01-01
  • 1970-01-01
  • 2012-12-30
  • 2014-01-20
  • 1970-01-01
  • 2019-01-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多