PHP预备语句调用的存储过程中的预备语句

问题描述 投票:0回答:1

我只是想从安全角度考虑这是否有任何优点。假设我有一个PHP脚本,需要从数据库中获取一些东西。用PHP编写并以这种方式使用预处理语句是否更安全,将所有内容封装在MySQL存储过程中是否更安全,或者实际上可以通过使用PHP Prepared语句来调用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 = $conn->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。这会增加额外的安全性吗?

php mysql stored-procedures prepared-statement sql-injection
1个回答
0
投票

坦率地说,通过使用直接在应用程序代码中准备和执行的SQL中的查询参数,存储过程无法提供同样简单有效的安全性。

并且存储过程在MySQL中更难开发。没有调试器,没有软件包支持,没有标准库,文档太薄且难以阅读,没有持久性编译器,等等。

在Microsoft / Oracle / IBM中,存储过程必须更加成熟,并且传统上为项目开发大型过程包。但是在MySQL中,我几乎从不使用存储过程。

对于防止SQL注入,请使用查询参数。这更容易,也同样有效。

© www.soinside.com 2019 - 2024. All rights reserved.