我正在修改我的代码,从使用mysql_*
to PDO
。在我的代码中,我有mysql_real_escape_string()
. 在 PDO 中这个等价物是什么?
6 回答
嗯,不,没有!
从技术上讲有,PDO::quote()
但很少使用,也不等同于mysql_real_escape_string()
这是正确的!如果您已经按照使用准备好的语句记录的正确方式使用 PDO ,那么它将保护您免受 MySQL 注入。
#Example:
下面是使用准备好的语句 (pdo) 进行安全数据库查询的示例
try {
// first connect to database with the PDO object.
$db = new \PDO("mysql:host=localhost;dbname=xxx;charset=utf8", "xxx", "xxx", [
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-injection 的影响。
值得注意的是,出于安全原因,您应该charset=utf8
在如上所示的那样传递 as 属性,DSN
并始终启用 PDO 以异常形式显示错误。
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
因此,来自您的数据库查询的错误不会泄露敏感数据,例如您的目录结构、数据库用户名等。
最后但并非最不重要的一点是,有时您不应该 100% 信任 PDO,并且必然会采取一些额外的措施来防止 sql 注入,其中一种情况是,如果您使用的是过时版本的 mysql [ mysql =< 5.3.6 ]
,如本文所述回答
但是,使用如上所示的准备好的语句总是比使用任何以mysql_
好读
MySQL 开发人员的 PDO 教程
空无一人*!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;");
* 好吧,正如迈克尔·伯科夫斯基所说,有一个!但是还有更好的方法。
$v = '"'.mysql_real_escape_string($v).'"';
相当于$v = $this->db->quote($v);
确保您有一个 PDO 实例,$this->db
因此您可以调用 pdo 方法quote()
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();
}
针对这里很多人的评论,但我还不能直接评论(未达到50分),$dbh->quote($value)
使用PDO时实际上需要使用EVEN,它们是完全正当的理由......
- 如果您正在循环构建“BULK INSERT”命令的许多记录,(我通常在 1000 条记录上重新启动)由于利用 MySQL/Maria Db 中的 InnoDb 表。使用准备好的语句创建单独的插入命令很简洁,但在执行批量任务时效率非常低!
- PDO 还不能处理动态 IN(...) 结构,因此当您从用户变量列表构建 IN 字符串列表时,您将需要
$dbh->quote($value)
列表中的每个值!
所以是的,$dbh->quote($value)
在使用 PDO 时需要,这可能是该命令首先可用的原因。
PS,您仍然不需要在命令周围加上引号,该$dbh->quote($value)
命令也会为您执行此操作。
出去。
如果要回答原始问题,那么这是 PDO 等效项mysql_real_escape_string
:
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);
}