我应采取哪些步骤来防止SQL注入?

时间:2012-03-04 07:54:13

标签: php sql-injection

在回复previous question I had posted时,有一个回复我正在打开我的数据库到SQL注入。代码如下:

    <?php


        $firstname = stripslashes(strip_tags($_POST['firstname']));

        $lastname = stripslashes(strip_tags($_POST['lastname']));
        $email = stripslashes(strip_tags($_POST['email']));
        $title = stripslashes(strip_tags($_POST['title']));
        $organization = stripslashes(strip_tags($_POST['organization']));


    $pdbHost = "localhost";
    $pdbUserName = "******";
    $pdbPassword = "******";
    $pdbName     = "db1080824_emails";



    //  Connect to mySQL
    $conlink = mysql_connect($pdbHost, $pdbUserName, $pdbPassword);
    if(!$conlink) {die('Unable to connect to '.$pdbHost);}
    if (!mysql_select_db($pdbName, $conlink)){die('Cannot find database '.$pdbName);}

    //SQL query

        $SQL2="INSERT INTO  `db1080824_emails`.`emails` (`record_id` ,`firstname`,`lastname`,`email`,`title`,`organization`)VALUES (NULL ,  '".$firstname."',  '".$lastname."',  '".$email."',  '".$title."',  '".$organization."')";

        mysql_query($SQL2);
    //  Connect to Closing the connection
    mysql_close($conlink);
?>

有人建议我可以对'/ ^ [A-Za-z0-9] /'进行服务器端验证检查,以确保不会发生sql注入,但这是否足够或是否有最佳实践我应该遵循以确保数据清理?

3 个答案:

答案 0 :(得分:3)

使用准备好的陈述。认真。一种简单的方法是使用PHP的数据库包装器PDO

$firstname = $_POST['firstname'];
$lastname = …;
…

$db = new PDO('mysql:host=hostname;dbname=dbname', 'username', 'password');
$stmt = $db->prepare('INSERT INTO  `db1080824_emails`.`emails` (`firstname`,`lastname`,`email`,`title`,`organization`)
  VALUES (:firstname, :lastname, :email, :title, :organization)');
$stmt->execute(array(
  ':firstname' => $firstname,
  ':lastname' => $lastname,
  ':email' => $email,
  ':title' => $title,
  ':organization' => $organization));

答案 1 :(得分:1)

使用mysql_real_escape_string()来阻止SQL注入。只有这个功能就足够了。

而且,@ knittl所说的,使用预准备语句也是防止它的一种非常好的方法。但正常的mysql_ * libary不支持这一点。你需要一个像PDO或MySQLi这样的库。我建议你切换到PDO或MySQLi,因为在更高的PHP版本中,mysql_ * libary会被弃用。

其他一些改进代码的提示:

  • 请勿使用die()。如果你犯了一个错误,你就不会死,为什么要一台电脑呢?最好处理错误并将它们放在你想要的位置。
  • mysql_close()不需要。 PHP在执行结束时关闭每个连接。
  • 对查询使用错误处理,如果查询返回false则存在问题。如果查询已完成某项操作,请与mysql_affected_rows()mysql_num_rows核对。

我要回答有关此答案的评论。您应该仅对字符串使用mysql_real_escape_ string 。如果您使用mysql_real_escape_string(),请确保在查询中的字符串周围加上引号('):

$query = "SELECT foo FROM bar WHERE name = '".mysql_real_escape_string($_POST['name'])."'";

如果你使用整数或任何其他数字,你应该使用typecasting而不是转义函数:

$query = "SELECT foo FROM bar WHERE id = ".(int) $_POST['id'];

答案 2 :(得分:0)

我一直在使用PDO,我相信这可以防止注射:

$db_user = "****";
$db_pass= "****";
$dsn = "mysql:dbname=yourdatabasename; host=localhost";
$dbh = new PDO($dsn, $db_user, $db_pass);

$sql = 'INSERT INTO
        emails(firstname, lastname, email, title, organization)
        VALUES(:firstname,:lastname,:email,:title,:organization)';
$data = array(':firstname'=>$firstname,
              ':lastname'=>$lastname,
              ':email'=>$email,
              ':title'=>$title,
              ':organization'=>$organization);

$sth = $dbh->prepare($sql);
$sth->execute($data);