需要帮助使PDO预处理语句更安全

时间:2015-09-11 16:20:33

标签: php mysql oop pdo

我正在用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)

提醒一下,这段代码非常合适,我只想知道它是否可以更安全。

谢谢。如果这是一个糟糕的问题,或者在错误的地方我很抱歉。

1 个答案:

答案 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>

还是更糟糕的事情?你也需要从你的输入中清除那些东西。