PDO :: prepare()不转义SQL中的特殊字符

时间:2013-06-25 23:33:49

标签: php mysql pdo escaping quoting

我有一个HTML textarea元素的输入值无法插入MySQL表,因为它包含撇号(')字符,例如:'Adam's garden'。所以我使用了PHP文档建议的PDO :: prepare()函数,但我仍然无法将这些数据插入到表中,但是当我删除撇号来获取'Adams garden'时,该值成功插入< / p>

我认为PDO::prepare()函数应该处理引号并转义SQL语句的特殊字符。 PHP文档确实说使用PDO::prepare()绑定参数,但我没有将我的php变量绑定到查询参数。绑定参数是绝对必要的还是只是说明,因为这是使用PDO::prepare()函数的常用方法?

我如何引用和转义输入变量中的特殊字符?

修改 我正在使用字符串连接来执行多个SQL INSERT。撇号位于下面示例代码的$evData['Description']字段中。

$evQuery ="INSERT INTO ep_events
        VALUES(NULL, '" .$evData['Title'] ."', '" .$evData['Venue'] ."', '" .$evData['Address'] ."', '" .$evData['Description'] ."')";


$tkQuery ="INSERT INTO ep_tickets VALUES";
foreach ($tkData as $ref =>$tkObj){
    for($i=0; $i<$tkObj['Quantity']; $i++){
        $tkQuery .='(NULL, LAST_INSERT_ID(), "' .$tkObj['Name'] .'", "' .$tkObj['Price'] .'"),';
    }
}

$tkQuery =rtrim($tkQuery, ',');

$query ='START TRANSACTION;' .$evQuery ."; " .$tkQuery .';' .'COMMIT;';
$stm =$db->prepare($query);     
$stm->execute();

这是PHP文档部分:

  

PDO :: quote()在输入字符串周围放置引号(如果需要),并使用适合于基础&gt;驱动程序的引用样式转义输入字符串中的特殊&gt;字符。

     

如果您正在使用此函数来构建SQL语句,那么您就是   强烈建议使用PDO :: prepare()来准备SQL语句   使用绑定参数而不是使用PDO :: quote()进行插值   用户输入到SQL语句中。带有约束的预备语句   参数不仅更便携,更方便,不受SQL的影响   注入,但通常比插值快得多   查询,因为服务器端和客户端都可以缓存已编译的表单   的查询。   http://www.php.net/manual/en/pdo.quote.php

2 个答案:

答案 0 :(得分:6)

PDO::prepare仅创建预备语句。查询必须正确参数化,您必须将参数发送到execute(或以其他方式绑定它们)才能正确转义。例如:

$ta = $_REQUEST['textarea'];
$stmt = $pdo->prepare("INSERT INTO t1 VALUES (?)");
$stmt->execute(array($ta));

你可能正在做的是

$pdo->prepare("INSERT INTO t1 VALUES ('" . $_REQUEST['ta'] . "')")->execute();

在这种情况下输入不会被转义。

答案 1 :(得分:0)

SQL语句是代码。当您使用串联(或其他)构建SQL查询时,您正在进行代码生成。当您生成PHP代码(eval ("echo '$variable';");)或HTML代码(<h1><?= $header?></h1>)时,此代码生成具有相同的问题。生成的代码中没有“数据”,只有代码本身。

有几种方法可以尝试避免不必要的行为。

  1. 打包/解包:使用base64_encode / FROM_BASE64作为数据库的数据变量,使用base64_encode / base64_decode作为eval,使用htmlentities作为html。

  2. 转义:$ PDO :: quote()用于数据库的数据变量,某些函数用于eval(例如return '\'' . str_replace(array('\\', '\''), array('\\\\', '\\\''), $var) . '\'';

  3. (坏)删除'危险'构造:(例如`$ v = preg_replace('/ UNION(?:\ s + ALL)?\ s + SELECT / i',' - ',$ a);)用于数据库,用于HTML的strip_tags。

  4. 从代码中分离数据:为数据库准备语句,生成函数并将数据传递给它以进行评估,使用文档对象模型构建HTML。

  5. 因此,预准备语句的主要思想是从代码中分离数据。因此,您必须直接指定数据的位置和代码的位置。

    使用预准备语句插入的最简单方法是

    $pdo->prepare('INSERT INTO `table` (`text`) VALUES(?);')->execute(array($text));
    

    请记住,准备好的陈述是避免麻烦的首选方式。如果你可以使用预备语句 - 使用它。