我正在将一些使用ext/mysql(mysql_*()函数)的代码转换为PDO和预处理语句.以前当我动态构建查询时,我只是通过我的字符串mysql_real_escape_string()直接将它们放入我的查询中,但现在我发现我需要在执行查询时将值作为数组传递,或者在执行之前绑定变量.
如何将旧代码转换为使用新的数据库驱动程序?
如果我使用MySQLi准备好的语句如下:
$stmt = $con1->prepare("UPDATE Login SET Session='LoggedOut' where Session=?");
$stmt->bind_param('s',$Session);
$stmt->execute();
$stmt->close();
Run Code Online (Sandbox Code Playgroud)
我还需要逃避我的变量,例如$Session用mysqli_real_escape_string();象下面这样:
$Session = mysqli_real_escape_string($con1, $_COOKIE['Session']);
$stmt = $con1->prepare("UPDATE Login SET Session='LoggedOut' where Session=?");
$stmt->bind_param('s',$Session);
$stmt->execute();
$stmt->close();
Run Code Online (Sandbox Code Playgroud) <?php # Nettuts Tutorial using PHP Data Objects (PDO),
/**This file contains the database access information
*This file also establishes a connection to mySQL
*and selects the database.
*Set the database access information as constants:
**/
// print_r(PDO::getAvailableDrivers());
DEFINE('DB_USER', 'root');
DEFINE('DB_PASSWORD', 'root');
DEFINE('DB_HOST', 'localhost');
DEFINE('DB_NAME', 'sitename');
$php = "htmlspecialchars";
try {
#MySQL with PDO_MYSQL
// $DBH = new PDO("mysql:host={$php(DB_HOST)}; dbname={$php(DB_NAME)}", root, root};
$DBH = new PDO("mysql:host=localhost; dbname= sitename", root, root);
$DBH->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
# UH-OH! Typed DELECT instead of SELECT!
$DBH->prepare('DELECT …Run Code Online (Sandbox Code Playgroud) 我是PHP的新手,还不熟悉它是如何工作的.
如果我使用mysqli_real_escape_string()并参数化SQL查询中的每个变量,我可以省去自己进行验证is_numeric()等吗?
创建注射检测系统的最佳方法是什么?用regex的东西简单验证用户的输入并将其保存在数据库中?
我的代码中有一些旧的mysql_query查询,我想将其转换为PDO,但我很难开始工作.
我原来的代码是:
mysql_query("UPDATE people SET price='$price', contact='$contact', fname='$fname', lname='$lname' WHERE id='$id' AND username='$username' ")
or die(mysql_error());
Run Code Online (Sandbox Code Playgroud)
现在我想:
$sql = "UPDATE people SET price='$price', contact='$contact', fname='$fname', lname='$lname' WHERE id='$id' AND username='$username'";
$q = $conn->query($sql) or die("failed!");
Run Code Online (Sandbox Code Playgroud)
但似乎无法让它发挥作用,任何想法?
更新的代码:
$conn = new PDO("mysql:host=$host;dbname=$db",$user,$pass);
// check if the form has been submitted. If it has, process the form and save it to the database
if (isset($_POST['submit']))
{
// confirm that the 'id' value is a valid integer before getting the form data
if …Run Code Online (Sandbox Code Playgroud) 我有这个问题要清理.我阅读了一些文档和评论,但仍然有些不够清楚.
但这是我的问题,使用预处理语句,我们是否必须使用参数绑定我们在语句中使用的数据?好的做法还是要?如果您多次运行相同的查询但是它足以保护查询本身,我理解准备好的语句是良好的性能?或绑定参数是必须的?具体的绑定参数是什么以及它如何保护数据免受sql注入?如果您指出我对上述陈述的任何误解,也将不胜感激.
谢谢
我有点困惑为什么我们需要指定在 Php 的 PDO 中的 bindParam() 函数中传递的数据类型。例如这个查询:
$calories = 150;
$colour = 'red';
$sth = $dbh->prepare('SELECT name, colour, calories
FROM fruit
WHERE calories < ? AND colour = ?');
$sth->bindParam(1, $calories, PDO::PARAM_INT);
$sth->bindParam(2, $colour, PDO::PARAM_STR, 12);
$sth->execute();
Run Code Online (Sandbox Code Playgroud)
如果不指定第三个参数,是否存在安全风险?我的意思是如果我只是在 bindParam() 中执行以下操作:
$sth->bindParam(1, $calories);
$sth->bindParam(2, $colour);
Run Code Online (Sandbox Code Playgroud) 两种准备好的陈述之间究竟有什么区别?
我认为真正准备好的语句需要服务器端支持,它在解析和编译sql代码的模式/模板之后接受参数,并且,我想,这就是保证我们防止sql注入的原因.
对于模拟准备好的语句,没有服务器支持,
它能保证我们不反对它吗?
我偶然发现了(imho相当糟糕的文档)事实,默认情况下,PHP PDO MYSQL_ATTR_DIRECT_QUERY为其MySQL驱动程序启用了标志.
这意味着它不是实际使用预准备语句,而是模拟预准备语句的行为.这意味着它使用转义值替换占位符客户端,并按原样将完整查询发送到数据库.
曾经有一个很好的理由这样做,因为在旧版本的MySQL预编译语句中会绕过查询缓存.但现在情况已经不是这样了.还有一点性能优势,因为它减少了从应用程序到数据库的往返次数,但我不确定这是值得的吗?
使用这种方法的明显缺点是我们仍然依赖于客户端转义,这通常是一个坏主意.我遇到了一些奇怪的问题,mysqli_real_escape_string过去由于某些字符集配置错误而允许无效字符进入查询.我宁愿不再有类似的事情再次发生.
我只是在这个问题上找到了半真半假和肤浅的评论(例如'是的,你可以启用'或'它会导致"问题"').寻找一个真正的原因,为什么我不打开它?在MySQL/PDO中使用实际准备好的语句无论如何都与模拟的预处理语句不兼容?
我问的部分原因是因为我们使用PHPActiverecord,它依赖于PDO.它不附带测试,我不希望它突然中断生产,因为关闭模拟的预准备语句会巧妙地改变某些边缘情况下的行为.
(作为旁注,在任何人提起之前:检查PDO::ATTR_EMULATE_PREPARES不起作用,因为它实际上没有(完全)为MySQL驱动程序实现,你必须检查PDO::MYSQL_ATTR_DIRECT_QUERY.是的,那个花了我一段时间.)
澄清:我想知道是否有充分的理由不关闭此行为.不是我不应该首先关心的原因.
我在想一个这样的例子:
请求使用参数在网址(通过任何方式)访问页面.example.com/api/page?name=bob.我的理解是你应该做一个准备好的声明来获取$_POST[name]参数,并确保它不是什么时髦,但它通过评估表达式来实现.
我的第一个问题是:它是如何做到的(评估表达式)?
我的第二个问题是:如果用户输入的内容沿着"SELECT*FROM users"或"DROP TABLE users"传递给$_POST['name']参数(?name=bob最后),那么在这种情况下会发生什么?
举个例子,最终的查询就像是
SELECT name, continent FROM world
WHERE continent IN
(SELECT continent FROM world WHERE name='Brazil')
Run Code Online (Sandbox Code Playgroud)
第二个选择充当用户输入参数 - 因此$_POST['name']包含此查询SELECT continent FROM world WHERE name='Brazil'
最后,我遇到的第三个问题是我如何防范类似的事情?
我猜PDO是专门为了防止查询内的查询而设计的(?),但是在阅读了一下之后我仍然很困惑.
我还在学习所有这些,所以如果我在我的询问中不够清楚或具体,请告诉我,我会尽力解决这个问题.
编辑: 为了清除任何困惑,我正在做的是这样的:
$pdo = new PDO('..');
$sql = 'SELECT id FROM users WHERE username = :username';
$statement = $pdo->prepare($sql);
$statement->bindParam(':username', $_POST['username']);
Run Code Online (Sandbox Code Playgroud)
问题是,如果$_POST['username']包含'SELECT * FROM users'(或任何其他查询)怎么办?prepare()工作怎么样?我所描述的实际上可以提出一个安全漏洞吗?我需要一些帮助来理解这一点.