你会建议我改变这些代码行吗?

时间:2016-03-09 23:07:55

标签: php mysql mysqli

我想说清楚*(所以人们不要急于推销这个,因为这对他们来说很容易。*):
我是一名初学程序员,是的,在完成一些基本的东西之后,我会转向mysqli,而不是pdo,这对我来说很复杂。

require('header.php');
$id = mysql_real_escape_string($_GET["id"]);
$userRow = mysql_query("SELECT * FROM table WHERE `id` = $id AND visible = 1");
$row = mysql_fetch_assoc($userRow);
$user_1 = $row['id'];
if ($user_1)
{
    echo function($user_1);
}else{
     echo 'Error 404';
}     

我如何从这段代码中避免sql注入,欢迎提出任何建议。

1 个答案:

答案 0 :(得分:3)

PHP 1.5中不推荐使用PHP中的mysql扩展 - 即使你刚刚开始使用PHP / MySQL,这些函数也不应该是你的起点。最小值应该是mysqli。 mysql_的大多数功能都具有mysqli_等效功能。

通常,您应该尝试通过将允许值列入白名单来减少攻击面:

  1. 如果您的ID是一个整数,那么请对其进行类型转换,例如:$userRow = mysql_query("SELECT * FROM table WHERE `id` = " . intval($_GET['id']) . " AND visible = 1");这将消除此查询的所有SQL注入。
  2. 如果只允许使用字母数字字符,请使用简单的正则表达式,例如$userRow = mysql_query("SELECT * FROM table WHERE `id` = \"" . preg_replace('/[^A-Za-z0-9]/', '', $_GET['id']) . "\" AND visible = 1"); - 除了A-Z,a-z和0-9之外的所有内容都将从字符串中删除。
  3. 如果您的ID是电子邮件地址或其他预定义格式,请使用filter_var - 只有在您收到的输入成功通过filter_var时才执行查询。
  4. 如果字符串中特别不允许某些字符可能导致SQL注入,则无论您如何使用$id = mysql_real_escape_string(preg_replace('[\'"]', '', $_GET["id"]));$id = mysql_real_escape_string(str_replace('"', '', str_replace('\'', '', $_GET["id"])));转义字符串,都要删除它们 - 这会删除所有&# 34;和'来自字符串,通常不需要。
  5. 如果允许任何字符串(在大多数应用程序中这应该是少数情况),mysqli_real_escape_string是一个不错的选择。在您的示例中,您仍然需要$ id周围的引号,例如$userRow = mysql_query("SELECT * FROM table WHERE `id` = '$id' AND visible = 1");棘手的部分是mysqli_real_escape_string取决于使用的字符集 - 也使用mysqli_set_charset()并将其设置为utf8。
  6. 如您所见,您需要自己做很多考虑和关心 - 在我看来这不值得。使用现有的库或框架,其中有很多想法用于防止SQL注入,并且有详细的文档以避免安全漏洞。 Doctrine是一个不错的选择(使用DBAL,您仍然可以以最小的开销自己进行查询)。您仍然可以将这些库包装在您自己的对象或类中,以便完全控制。

    如果你只想使用PHP的内置方法,那么PDO并不难。这是一个使用未命名占位符的示例:

    $db = new PDO("dbtype:host=yourhost;dbname=yourdbname;charset=utf8","username","password");
    
    $insecuredata = $_GET["id"];
    
    $query = $db->prepare("SELECT * FROM table WHERE id = ? AND visible = 1");
    $query->execute(array($insecuredata));
    $row = $query->fetch(PDO::FETCH_ASSOC);
    

    此示例使用命名参数,这样可以轻松扩展查询(有几种方法可以执行此操作,$ query-&gt; bindParam也很有可能 - 请参阅PDOStatement::execute的PHP文档):< / p>

    $db = new PDO("dbtype:host=yourhost;dbname=yourdbname;charset=utf8","username","password");
    
    $insecuredata = $_GET["id"];
    
    $query = $db->prepare("SELECT * FROM table WHERE id = :id AND visible = 1");
    $query->execute(array(':id' => $insecuredata));
    $row = $query->fetch(PDO::FETCH_ASSOC);
    

    习惯PHP和现有框架为您提供的可能性 - 他们都经历了漫长的学习过程,以消除问题和安全漏洞。你真的想以最难的方式学习所有可能的问题吗?

相关问题