我正在用PHP构建自定义CMS,我有想法从数组生成MySQL。我猜这不是最安全的事情,因为我将变量直接放入预处理语句中。我希望有经验的人可以看看我到目前为止所做的事情,并让我深入了解如何让这更安全。
这是我将所有数据操作方法存储在
中的类abstract class MySQLData extends MySQLDataHelper {
// connection to database
abstract public function getConn();
// table name from concrete class
abstract public function getTable();
public function insert( $args ) {
try {
$stmt = $this->getConn()->prepare( $this->generateInsertSQL( $args ) );
foreach ($args as $arg => &$value) {
$stmt->bindParam(":{$arg}", $value);
}
$stmt->execute();
} catch (PDOException $e) {
echo "Insert error: " . $e->getMessage();
}
}
//............................................
// More methods below, including delete, select and update, but lets focus on 'insert' only to keep things simple.
}
Helper方法类,包括插入SQL生成器
abstract class MySQLDataHelper {
public function generateInsertSQL( $args ) {
$columns = array_keys( $args );
$placeholders = implode(', :', $columns);
$columns = implode(', ', $columns);
return "INSERT INTO `{$this->getTable()}` ({$columns}) VALUES (:{$placeholders})";
}
}
示例用例
require_once 'core/Pages.php';
$pages = new Pages( $db->conn() ); // Pages extends MySQLData
$args = array(
'name' => 'New page',
'content' => 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quisquam, laboriosam!',
'enabled' => true);
$pages->insert( $args );
请注意,在这种情况下,generateInsertSQL的输出将是:
INSERT INTO `pages` (name, content, enabled) VALUES (:name, :content, :enabled)
提醒一下,这段代码非常合适,我只想知道它是否可以更安全。
谢谢。如果这是一个糟糕的问题,或者在错误的地方我很抱歉。
答案 0 :(得分:0)
这是社区维基的答案。任何人都可以编辑它以响铃。
绑定变量解决的问题是这样的:SQL是一种语言,当你通过插入数据就像文本一样用语言汇编语句时,你为不受信任的人提供了一种扩展SQL程序的方法
所以,你必须努力消毒一切。例如,如果您正在做这种事情:
id IN (4 5,6,7)
确保所有数字实际上都是数字并不太难。但是你必须每次都这样做,而不是失败,或者是为了实现目标。另一方面,如果你正在做
name IN ('cyanographics', 'Rocket Hazmat', 'Fred -ii-1')
并且有人向您提供恶意用户名 - 想想
cyano'); DELETE FROM TABLE USER CASCADE CONSTRAINTS; //
您最终会要求您的SQL语言解释程序运行它。
name IN ('cyano'); DELETE FROM TABLE users CASCADE CONSTRAINTS; //', 'Rocket Hazmat', 'Fred -ii-1')
这种事情可能会使您的应用程序大为混乱。
因此,您需要仔细考虑如何清理文本输入。您可以考虑使用PDO::quote()之类的内容清理文本字符串。它将转义序列放在字符串中的危险字符(如'
)周围。
但是看起来,你最好在PDO中使用内置的绑定变量支持,即使你更难处理你想要处理的列表。
阅读本文:What are the best PHP input sanitizing functions?
另外,不要忘记考虑浏览器脚本注入。如果您提供了名称
,该怎么办? <script>alert('You are pwned, sucka!');</script>
还是更糟糕的事情?你也需要从你的输入中清除那些东西。