什么是PDO等效函数mysql_real_escape_string?

时间:2012-12-23 16:32:04

标签: php mysql pdo sql-injection

我正在修改使用mysql_*PDO的代码。在我的代码中,我有mysql_real_escape_string()。在PDO中这相当于什么?

6 个答案:

答案 0 :(得分:63)

嗯不,没有!

从技术上讲,有PDO::quote(),但很少使用它,并不等同于mysql_real_escape_string()

这是对的!如果您已经使用prepared statements记录的正确方式使用PDO,那么它将保护您免受MySQL注入。


Example:

以下是使用预准备语句(pdo)的安全数据库查询的示例

  try {
     // first connect to database with the PDO object. 
     $db = new \PDO("mysql:host=localhost;dbname=xx;charset=utf8", "xx", "xx", [
       PDO::ATTR_EMULATE_PREPARES => false, 
       PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
     ]); 
 } catch(\PDOException $e){
     // if connection fails, show PDO error. 
   echo "Error connecting to mysql: " . $e->getMessage();
 }

而且,现在假设已建立连接,您可以像这样执行查询。

if($_POST && isset($_POST['color'])){ 

    // preparing a statement
    $stmt = $db->prepare("SELECT id, name, color FROM Cars WHERE color = ?");

    // execute/run the statement. 
    $stmt->execute(array($_POST['color']));

    // fetch the result. 
    $cars = $stmt->fetchAll(\PDO::FETCH_ASSOC); 
    var_dump($cars); 
 }

现在,正如您可能已经知道的那样,我没有使用任何东西来逃避/消毒$_POST["color"]的价值。由于PDO和预处理语句的强大功能,此代码对于myql注入是安全的。


值得注意的是,出于安全原因,您应该在charset=utf8中传递DSN属性,并始终启用 PDO以异常的形式显示错误。

PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION

因此,数据库查询中的错误不会泄露敏感数据,如目录结构,数据库用户名等。

最后但并非最不重要的是,有些时候你不应该信任PDO 100%,并且必然要采取一些额外的措施来防止sql注入,其中一种情况是,如果你使用的是过时版本的mysql { {1}} described in this answer

但是,使用上面显示的预准备语句总是比使用以[ mysql =< 5.3.6 ]

开头的任何函数更安全

好读

PDO Tutorial for MySQL Developers

答案 1 :(得分:26)

没有*! PDO的目标是你不必逃避任何事情;你只需将其作为数据发送。例如:

$query = $link->prepare('SELECT * FROM users WHERE username = :name LIMIT 1;');
$query->execute([':name' => $username]); # No need to escape it!

相反:

$safe_username = mysql_real_escape_string($username);
mysql_query("SELECT * FROM users WHERE username = '$safe_username' LIMIT 1;");

*好吧,有一个,正如Michael Berkowski所说的那样!但还有更好的方法。

答案 2 :(得分:5)

$v = '"'.mysql_real_escape_string($v).'"'; 

相当于$v = $this->db->quote($v); 确保您在$this->db中有一个PDO实例,因此您可以调用pdo方法quote()

答案 3 :(得分:1)

在PDO中不需要 mysql_real_escape_string

PDO本身会调整mysql查询中的特殊字符,您只需要传递匿名参数并绑定它的运行时间即可。 假设您有一个带有属性名称,电子邮件和密码的用户表,并且您必须像这样插入使用准备语句 您可以将名称传递为=> $ name =“ Rajes'h”;

它应该执行,不需要等效的 mysql_real_escape_string

$stmt="INSERT into user(name,email,password) VALUES(:name,:email,:password)";
try{
   $pstmt=$dbh->prepare($stmt);//$dbh database handler for executing mysql query
   $pstmt->bindParam(':name',$name,PDO::PARAM_STR);
   $pstmt->bindParam(':email',$email,PDO::PARAM_STR);
   $pstmt->bindParam(':password',$password,PDO::PARAM_STR);
   $status=$pstmt->execute();
   if($status){
    //next line of code 
   }


}catch(PDOException $pdo){
     echo $pdo->getMessage();
}

答案 4 :(得分:-2)

如果要回答原始问题,那么这是mysql_real_escape_string的等效PDO:

function my_real_escape_string($value, $connection) {
    /* 
    // this fails on: value="hello'";
    return trim ($connection->quote($value), "'");
    */
    return substr($connection->quote($value), 1, -1);       
}
顺便说一下,mysqli的等价物是:

function my_real_escape_string($value, $connection) {
    return mysqli_real_escape_string($connection, $value);
}

答案 5 :(得分:-2)

为了回应很多人对此的评论,但我还不能直接发表评论(未达到50分),实际上在使用PDO时甚至需要使用$dbh->quote($value),而且完全可以辩解原因...

  1. 如果要遍历许多记录来构建“ BULK INSERT”命令,(通常我会重新启动1000条记录),这是由于利用了MySQL / Maria Db中的InnoDb表。使用准备好的语句创建单个插入命令很简洁,但是在执行批量任务时效率很低!
  2. PDO尚不能处理动态IN(...)结构,因此当您从用户变量列表构建IN字符串列表时,您将需要$dbh->quote($value)列表中的每个值!

所以,是的,使用PDO时需要$dbh->quote($value),并且可能为什么该命令首先可用。

PS,您仍然不需要在命令两边加上引号,$dbh->quote($value)命令也可以为您完成。

出去。