我正在努力自动化部署我编写的软件,并且需要能够为新帐户生成新的mysql数据库。 但是,在清理输入时,我感到担忧。
我正在使用PDO;但是,显然你不能将准备好的语句与"创建数据库"一起使用。 所以,我也尝试使用PDO::quote;但是,我新创建的数据库名称被单引号包围(不是世界末日,但我仍然想避免这种情况)。
有没有办法让它与准备好的语句一起工作? 如果没有,我该怎么做才能尽可能地保护自己免受 sql 注入攻击? 我唯一的另一个想法是允许一个小的字符白名单。
谢谢!
您需要
编写一个存储过程,然后将清理后的输入传递给该过程(使用我的例子,你需要改变一些变量,如数据库名称和正确的用户和传递等,当然要让它在你的数据库上运行)
例:
<?php
$dsn = 'mysql:dbname=scratch;host=127.0.0.1';
$user = 'root';
$password = '';
try {
$dbh = new PDO($dsn, $user, $password);
} catch (PDOException $e) {
echo 'Connection failed: ' . $e->getMessage();
}
$dbname = 'brand_new_db';
$statement = $dbh->prepare("CALL dbcreator(:db)");
$statement->bindParam(':db',$dbname);
if(!$statement->execute()){
print_r($statement->errorInfo());
}
else {
foreach( $dbh->query('SHOW DATABASES')->fetchAll() as $row){
print "$row[0]" . PHP_EOL;
}
}
存储过程:
DELIMITER $$
DROP PROCEDURE IF EXISTS `scratch`.`dbcreator` $$
CREATE DEFINER=`root`@`localhost` PROCEDURE `dbcreator`(IN dbname VARCHAR(64))
BEGIN
SET @db = dbname;
SET @statement = CONCAT('CREATE DATABASE ',@db);
PREPARE prepared_statement FROM @statement;
EXECUTE prepared_statement;
END $$
DELIMITER ;
你创建一个SQL语句来准备,在我们的例子中CREATE DATABASE <our database>;
因为CREATE DATABASE
语句不适用于变量,然后你只是执行它。最后,执行执行存储过程CALL dbcreator('<dbname>')
。正是那个CALL dbcreator(:dbname)
,您可以使用参数并将其绑定到。
如您所见,这样您仍然可以在创建数据库时通过 pdo 安全地绑定参数。尽管如此,在您创建的所有数据库前面加上一些简短的固定字符串以便于查找和区分可能不是一个坏主意。在存储过程中,dbname 限制为 64 个字符,因为这是 mysql 的当前限制