php - PHP 预准备语句调用的存储过程内部的预准备语句

标签 php mysql stored-procedures prepared-statement sql-injection

我只是想知道从安全角度来看这是否有任何优点。假设我有一个 PHP 脚本,需要从数据库中获取一些内容。用 PHP 写出来并以这种方式使用准备好的语句是否更安全,将所有内容封装在 MySQL 存储过程中是否更安全,或者我实际上可以通过使用 PHP 准备好的语句调用 MySQL 存储来获得任何安全优势吗?其中包含准备好的语句的过程。或者只要我在某处使用准备好的语句就真的不重要吗?类似于以下内容,但可能更复杂一点:

PHP:

require 'path/to/login_utils.php';

try {
    $username = sanitize_validate_username($_POST['username']); // custom cleaning function from login_utils
    $pdo = connect_to_database(); // custom connection function from login_utils
    $select = "SELECT `password`
               FROM `tbl_login`
               WHERE `username`=:username;";
    $prepared = $pdo->prepare($select);
    $prepared->bindValue(":username", $username);
    $prepared->execute();
    $result = $prepared->fetchAll(PDO::FETCH_ASSOC);
    $prepared->closeCursor();
    if (isset($result) && count($result) > 0) {
        $password = $result['password'];
    }
} catch (PDOException $e) {
    die $e->getCode() . ': ' . $e->getMessage();
} finally {
    if (isset($pdo)) {
        unset($pdo);
    }
}
$userpass = $_POST['userpass'];
if (!isset($password) || !password_verify($userpass, $password)) {
    die 'Invalid username and password combo';
}
start_authenticated_session(); // custom session starting function from login_utils
echo 'You have been logged in';
exit;

但是如果我不是在 PHP 中动态地进行 SELECT,而是将其放在像这样的存储过程后面呢?

MySQL:

DELIMITER $$
CREATE PROCEDURE usp_GetUserPassword(IN @username VARCHAR(255))
this_proc: BEGIN
    IF @username IS NULL
        THEN LEAVE this_proc;
    END IF;

    DECLARE @password VARCHAR(64);
    PREPARE get_password
    FROM 'SET @password = (
              SELECT `password`
              FROM `tbl_login`
              WHERE `username`=?
          );';
    EXECUTE get_password USING @username;
    DEALLOCATE PREPARE get_password;
    SELECT @password;
END$$
DELIMITER ;

然后在我的 PHP 脚本中调用它,用以下内容替换第一个 SELECT:

$select = "CALL usp_GetUserPassword(:username);";

或类似的东西,我继续在 PHP 中准备和执行 $select,即使存储过程内部有一个准备好的语句。这会增加额外的安全性吗?

最佳答案

坦率地说,存储过程所提供的安全性是无法通过在 SQL 中使用直接从应用程序代码准备和执行的查询参数来轻松有效地获得的。

而且存储过程在MySQL中开发起来比较困难。没有调试器,没有包支持,没有标准库,文档很薄且难以阅读,没有持久的编译器,等等。

在Microsoft/Oracle/IBM,存储过程更加成熟,为项目开发大的过程包是传统的做法。但在 MySQL 中,我几乎从不使用存储过程。

为了防止 SQL 注入(inject),请使用查询参数。它更容易而且同样有效。

关于php - PHP 预准备语句调用的存储过程内部的预准备语句,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59727539/

相关文章:

php - Laravel/ Eloquent : hasManyThrough WHERE

php - 如何在 mysql 中存储 html_entites 作为它们的表示而不是它们的值

mysql - 使用 ALTER 编辑存储过程?

c# - 如何使用存储过程?

mysql - 存储过程在应该返回任何值时没有返回任何值(MySQL)

php - 具有相同名称的多个表单数据

php - 如何在此回调中获取 json 消息

Python mysql.connect SQL 查询中的整数

php - file_get_contents 用于插入数据库

MySQL:通过另一个表的总和更新表记录