12

我对 PDO 还很陌生,想知道下面的查询是否可以避免 SQL 注入。如果是这样,我将在整个站点中使用此方法。

    // make connection to DB
$db = new PDO('mysql:host='.$dateBaseHost.';dbname='.$dateBaseName, $dateBaseUsername, $dateBasePassword);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);


//simple query and binding with results
$query = $db->prepare(" SELECT * FROM `profile` WHERE `fullname` = :fullname ");

$search = (isset($_GET['search']) === true) ? $_GET['search'] : '' ; // ? : shorthand for if else

// bind parameters - avoids SQL injection
$query->bindValue(':fullname', $search);

//try... if not catch exception
try {
    // run the query
    $query->execute();

    $rows = $query->fetchAll(PDO::FETCH_ASSOC);
    echo '<pre>', print_r($rows, true),'</pre>';
}
catch (PDOException $e){
    sendErrorMail($e->getMessage(), $e->getFile(), $e->getLine());
}
4

4 回答 4

8

是的 - 以这种方式使用时,参数化查询不会被注入。

于 2013-03-18T16:36:04.427 回答
5

只要您正确使用准备好的语句,您就不会被注入。但是只要您将任何外部数据直接插入到查询中,即使它是一个准备好的语句,例如

INSERT INTO $table VALUES (:param)

你很脆弱 -$table在这种情况下可能会被颠覆,即使你使用的是准备好的语句。

任何告诉你简单地切换 mysql->PDO 或 mysqli 会让你更安全的人是完全错误的。使用任何一个库,您都可能同样容易受到注入攻击。

于 2013-03-18T16:38:18.313 回答
3

你还应该

$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

默认情况下,它使用模拟模式,它只是做的mysql_real_escape_string。在某些边缘情况下,您仍然容易受到 SQL 注入的攻击。

于 2013-03-18T16:43:59.400 回答
0

是的,它相当安全,但整个脚本可以改进:

if (isset($_GET['search']) {
    // make connection to DB
    $opt = array(
        PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
    );
    $dsn = "mysql:host=$dateBaseHost;dbname=$dateBaseName;charset=$dateBaseCharset";
    $db  = new PDO($dsn, $dateBaseUsername, $dateBasePassword, $opt);

    //simple query and binding with results
    $query = $db->prepare("SELECT * FROM profile WHERE fullname = ?");
    $query->execute(array($_GET['search']));
    $rows = $query->fetchAll();
    echo '<pre>', print_r($rows, true),'</pre>';
}
  • 您需要将 errmode 设置为连接选项
  • 永远不要使用 try..catch 来处理错误信息。如果您想针对每个错误发送一封电子邮件(这太疯狂了),您必须为此进行设置my_exception handler()
  • 将搜索设置为空字符串没有任何意义
  • 连接到 PDO 应该移动到单独的文件(未显示)
  • 字符集必须在 DSN 中设置
于 2013-03-18T16:39:33.303 回答