PHP - 这样我从我的数据库更新和 select 安全吗?

PHP - Is this way I update and select from my database secure?

最近改用PDO,想问一下是否和我一样安全?

(我之前用php提供的很多过滤方法过滤数据)

查询数据库:

 include 'path_to_config_file_with_login_creds_for_db.php';
        $options = array(
            PDO::ATTR_ERRMODE => PDO::ERRMODE_SILENT,
            PDO::ATTR_PERSISTENT => false,
        );

        try {
            $pdo = new PDO('mysql:host=' . $database_host . ';dbname=' . $database_name . ';charset=utf8mb4', $database_user, $database_pass, $options);
            $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
        } catch (PDOException $exception) {
            die("some error message");
        }

        try {
            $statement = $pdo->prepare($sql);
            $statement->execute($bindings);

            $statement->closeCursor();
            return $output;
        } catch (PDOException $stmEx) {
            die("again some error message");
        }

更新数据库:

   include 'again_path_to_config_file_where_creds_to_db.php';
        $options = array(
            PDO::ATTR_ERRMODE => PDO::ERRMODE_SILENT,
            PDO::ATTR_PERSISTENT => false,
        );

        try {
            $pdo = new PDO('mysql:host=' . $database_host . ';dbname=' . $database_name . ';charset=utf8mb4', $database_user, $database_pass, $options);
            $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
        } catch (PDOException $exception) {
            die("...");
        }

        try {
            $statement = $pdo->prepare($sql);
            $statement->execute($bindings);
            $statement->closeCursor();
        } catch (PDOException $stmEx) {
            die("...");
        }

这种方式安全吗?

一切正常,但我也想知道它是否安全

关于SQL注入,只要你参数化所有的输入和白名单所有动态SQL部分,你应该是安全的。

但是,您的代码还有另一个严重的问题。您正在消除错误。 PDO::ATTR_ERRMODE 应设置为 PDO::ERRMODE_EXCEPTION。但是,这会使您的代码处于更糟糕的状态,因为到处都是 die 。除非您有非常充分的理由,否则不要捕获异常。阅读这篇文章https://phpdelusions.net/pdo#errors

沉默或向用户显示错误会打开新的利用途径。这就是为什么最好的做法是让他们独自一人。在生产系统中,您应该将配置设置为从不显示错误。他们将安全地登录到服务器上。

从安全的角度来看,只要 $sql 中的查询正确使用参数绑定就应该是安全的。如果 $sql 变量是这样构建的,那么您的代码将无济于事。

//DO NOT TRY THIS AT HOME
$sql = "SELECT * FROM `users` WHERE user='" . $_POST['user'] . "'";

但我可以看到您的代码还有其他几个问题。

1) 你的 try ... catch 块没用。当您使用 PDO::ERRMODE_SILENT 时,PDO 不会引发任何异常。遇到错误时,只会设置 $pdo->errorCode$statement->errorCode 属性。

2) 您打开的连接太多。我假设您拥有在计划调用的某个函数中共享的代码,例如 queryDb($sql, $params); 这意味着每次调用该函数时,您都将创建 PDO 的新实例并打开新连接.您可能希望将创建 PDO 实例的部分移动到 db-config 文件中,然后每次您要使用 $pdo->prepare().

创建新语句时使用该单个实例

3) die的使用。在示例中查询出错时,通常的做法是使用 dieexit。但在实际应用中,这意味着用户会看到丑陋的空白页面,只有一句话说出了问题。最好抛出一个将在您的应用程序中更高级别处理的异常。这将使应用程序显示带有菜单和其他内容的页面布局,即使请求的操作失败也是如此。

4) 您没有在代码的第一部分 "Query DB" 中将值设置为 $output 变量。虽然我不确定你是在复制时遗漏了它,还是在你的实际代码中有这样的东西。