我开始知道在使用MySQLi和PDO时预备语句是如何工作的,第一步,我启用了MySQL查询监控,如下所述:我如何查看实时MySQL查询?.然后我创建了以下测试:
使用mysqli:
$stmt = $mysqli->prepare("SELECT * FROM users WHERE username =?")) {
$stmt->bind_param("i", $user);
$user = "''1''";
Run Code Online (Sandbox Code Playgroud)
服务器日志:
Run Code Online (Sandbox Code Playgroud)130802 23:39:39 175 Connect ****@localhost on testdb 175 Prepare SELECT * FROM users WHERE username =? 175 Execute SELECT * FROM users WHERE username =0 175 Quit
使用PDO:
$user = "''1''";
$sql = 'SELECT * FROM user WHERE uid =?';
$sth = $dbh->prepare($sql, array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY));
$sth->bindParam(1, $user, PDO::PARAM_INT);
Run Code Online (Sandbox Code Playgroud)
服务器日志:
Run Code Online (Sandbox Code Playgroud)130802 23:41:42 176 Connect ****@localhost on testdb 176 Query SELECT * FROM user WHERE uid ='\'\'1\'\'' 176 Quit
但是,两者都提供相同的结果:
uid: 0
username: admin
role: admin
Run Code Online (Sandbox Code Playgroud)
注意:uid = 0是正确的,因为intval("''1''") = 0
这里有什么重要的:
SELECT * FROM user WHERE uid ='\'\'1\'\''
我发现PHP手册中只有一个指示:http://www.php.net/manual/en/pdo.prepare.php
注意:
模拟的预准备语句不与数据库服务器通信,因此PDO :: prepare()不检查语句.
但我不确定MySQL如何处理此查询并替换'\'\'1\'\''为0.在这种情况下,如果使用PDO,监控查询将不准确,同时,使用PDO更好地了解发送到MySQL而不是MySQLi的确切查询.
更新: 将参数类型frm integer更改为string后:
MySQLi日志:
Run Code Online (Sandbox Code Playgroud)188 Prepare SELECT * FROM awa_user WHERE username =? 188 Execute SELECT * FROM awa_user WHERE username ='\'\'1\'\'' 188 Quit
PDO日志:
Run Code Online (Sandbox Code Playgroud)189 Query SELECT * FROM awa_user WHERE userame ='\'\'1\'\'' 189 Quit
这意味着MySQLi和PDO在使用字符串发送到MySQL之前转义数据,而对于整数,mysqli在发送查询之前应用intval()或类似的东西,Bill也回答这是正确的.
您的PDO配置为模拟准备好的查询,而mysqli使用真正准备的查询.
准备好的查询将字符串绑定''1''为整数参数值.PHP使用类似的东西将它强制转换为整数intval().任何带有非数字前导字符的字符串都被PHP解释为0,因此在 prepare 之后发送的参数值是值0.
伪造的查询使用字符串插值(而不是绑定)在 MySQL解析之前将字符串添加''1''到SQL查询中.但结果是类似的,因为SQL还将整数上下文中带有非数字前导字符的字符串视为值0.
唯一的区别是当参数在准备之前与准备之后绑定时,一般查询日志中会出现什么.
您还可以使PDO使用真正准备好的查询,因此在这种情况下它应该像mysqli一样:
$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
Run Code Online (Sandbox Code Playgroud)
PS:这可能是一个很好的理由,为什么习惯将id值设置为1而不是0.
| 归档时间: |
|
| 查看次数: |
1210 次 |
| 最近记录: |