理解准备语句 - PHP

时间:2012-12-21 17:09:58

标签: php mysql sql prepared-statement sql-injection

我正在为一所大学的财政援助办公室开展一个学校项目。该项目已投入生产,其中大部分已完成,除了一些小调整之外。我对冬歇期(现在)的主要关注是安全,并尽我所能防止任何违规行为。人们告诉我要引导准备好的陈述。除了插入数据之外,我在很大程度上理解它们。

我有两种形式:登录表格和学生登录表格。学生登录表输入学生来办公室的原因。然后提交该表格,然后通过一张表格检索该数据,该表格显示了辅导员学生们等待观看的内容。

我的问题是,每个走进经济援助办公室的学生都有自己独特的问题(大部分时间),所以现在让我困惑的是:

我是否需要提前考虑并预先制作插入查询,或者是否有办法进行“动态”查询,因为有一个学生评论框,为此它将是完全独特的,所以我将如何能够为此创建查询?

<?php
define('DB_Name', 'dbtest');
define('DB_User', 'root');
define('DB_Password', 'testdbpass');
define('DB_Host', 'localhost');

$link = mysql_connect(DB_Host, DB_User, DB_Password);

if (!$link) {
  die ('Could Not Connect: ' . mysql_error ());
}

$db_selected = mysql_select_db(DB_Name, $link);

if (!db_selected) {
  die('Can Not Use ' . DB_name . ': ' . mysql_error());
}

$value1 = $_POST ['anum'];
$value2 = $_POST ['first'];
$value3 = $_POST ['last'];
$value4 = $_POST ['why'];
$value5 = $_POST ['comments'];

$sql = "INSERT INTO `dbfinaid` (anum, first, last, why, comments) VALUES ('$value1', '$value2', '$value3', '$value4', '$value5')";

if (!mysql_query($sql)) {
  die('Error : ' . mysql_error());
}

mysql_close();

并且我被告知这样做会让我容易进行SQL注入。

非常感谢任何帮助。谢谢。

2 个答案:

答案 0 :(得分:6)

读完PHP's PDO后,您可以像这样重写代码

$dbh = new PDO('mysql:host=localhost;dbname=dbtest', $user, $pass);

try {
  $query = $dbh->prepare("INSERT INTO `dbfinaid` (anum, first, last, why, comments) VALUES (:anum, :first, :last, :why, :comments)");

  $query->bindParam(':anum',     $_POST['anum'],     PDO::PARAM_INT);
  $query->bindParam(':first',    $_POST['first'],    PDO::PARAM_STR);
  $query->bindParam(':last',     $_POST['last'],     PDO::PARAM_STR);
  $query->bindParam(':why',      $_POST['why'],      PDO::PARAM_STR);
  $query->bindParam(':comments', $_POST['comments'], PDO::PARAM_STR);

  $query->execute();
}
catch (PDOException $e) {
  die("error occured:" . $e->getMessage());
}

答案 1 :(得分:5)

基于@maček的答案,这是另一种做同样事情的方法。我发现这更容易:

$dbh = new PDO('mysql:host=localhost;dbname=dbtest', $user, $pass);

try {
  $query = $dbh->prepare("INSERT INTO `dbfinaid` (anum, first, last, why, comments)
    VALUES (:anum, :first, :last, :why, :comments)");

  $params = array_intersect_key($_POST, array_flip(array('anum', 'first', 'last', 'why', 'comments')));
  $query->execute($params);
}
catch (PDOException $e) {
  error_log($e->getMessage());
  die("An error occurred, contact the site administrator.");
}

我更喜欢将SQL错误输出到日志中,并向用户显示不同的错误,不会将错误与代码详细信息混淆。