从mysql真正的转义迁移到PDO,使其更健壮?

时间:2011-05-04 14:55:32

标签: php sql-injection

让我们看一个真实的例子;接下来的代码是我迄今为止所使用的以及ver ha da问题,但最近,由于索尼新闻等,我觉得我需要更多地了解这个主题“安全性”。

所以这是我的代码,下面的这些函数是一个类的方法,但由于时间原因,我无法向你展示一切

与我的数据库的连接

   function SQLinit($debug = 0)
   {
         $svr_msconnect = @mysql_connect($sql["db_host"], $sql["db_login"], $sql["db_pass"]);
         @mysql_select_db($sql["db_data"]);
         if (!$svr_msconnect)
         {
           echo mysql_error();
           exit;
         }
   }

调用查询的功能

   function DoQuery($sql, $assoc=0)
   {
        if (!$svr_msconnect) SQLinit();

        $result = mysql_query($sql, $svr_msconnect);

        if (mysql_errno())
        {
            //error alert....
            exit;
        }

        if ($result === TRUE) return array();        
        $res = array();

        if ($assoc)
            while ($row = mysql_fetch_assoc($result))
                array_push($res, $row);
        else
            while ($row = mysql_fetch_row($result)  ) 
                array_push($res, $row);

        return $res;
   } 

然后是简单用户身份验证的真正示例

     if(isset($_GET["e"]) && isset($_GET["p"])){

         $e = $_GET["e"];
         $p = $_GET["p"];       

         SQLinit();

         $e = mysql_real_escape_string($e);
         $p = mysql_real_escape_string($p);
         $p = md5($p);

        $sql = "SELECT user_id,user_email,user_pass FROM user_tb where user_email='$e' AND user_pass= '$p' ";
        $result = DoQuery($sql,1);
    }

所以基本上我的$ result是一个具有我需要的值的数组(员工姓名,书名,等等......)

我的问题:

我不想在这里讨论MD5或使用salt,但鉴于这是我已经实现的代码,并且已经在50多个文件中传播,有一种方法可以将我的代码转换为PDO方法吗?

我必须说我对PDO方法一无所知,我只是看了一些例子,但它们太理论化了,没有足够的背景......这里我有一个特定的背景要解决......

2 个答案:

答案 0 :(得分:1)

PDO允许使用预准备语句,因此您的代码看起来像这样:

$pdo = new PDO( ... params ... );
$stmt = $pdo->prepare("SELECT user_id,user_email,user_pass FROM user_tb where user_email = ? AND user_pass = MD5( ? ) ");

// If you have a User class, you can load it 
// otherwise you get an array
$stmt->setFetchMode(PDO_FETCH_CLASS, 'User');

$stmt->execute(array($_POST["e"], $_POST["p"]));
$user = $stmt->fetch();

有一点需要注意:如果有可能其他人(例如在共享服务器上运行)读取查询日志,则应先将密码首先哈希,然后再将其发送给PDO,但任何使用'或其他人的密码在密码中转义的字符需要重置,因为哈希值会有所不同。

有关获取模式魔法的更多信息,请参阅http://www.php.net/manual/en/pdostatement.setfetchmode.php

答案 1 :(得分:1)

首先,PHP Data Objects Extension只是用于访问和使用数据库的机制。如果您想学习如何使用PDO库,请查看documentation。但是,您可以在不使用PHP的PDO扩展的情况下创建安全的数据库实现。

您当前的实现并不算太差,但我肯定会建议 NOT 通过URI查询传递用户凭据(即使用$ _POST代替$ _GET来获取更敏感的参数)。