2012-03-04 80 views
1

在响应previous question I had posted,还有就是我被我的数据库对外开放SQL注入的响应。我应该采取哪些措施来防止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注入可能发生,但有足够的:下面的代码是给还是应该遵循以确保数据卫生的最佳做法?

+0

http://en.wikipedia.org/wiki/SQL_injection - 阅读更多关于它是如何做和浩w“撤销” – Joseph 2012-03-04 07:55:51

+1

只使用以前准备好的语句。期。 – knittl 2012-03-04 07:59:06

+3

第一步:**停止使用mysql_query **并使用像PDO或mysqli这样的现代API。两者都支持预准备语句 - 如果使用得当,可以大大减少SQL注入的时间。 – cHao 2012-03-04 08:00:21

回答

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

使用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_ 字符串。如果使用的是mysql_real_escape_string()要确保你已经把串绕引号(')查询:

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

如果使用intergers或任何其他号码,你应该使用typecasting而不是逃生功能:

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

您可以使用mysql_real_escape_string,但前提是您知道自己在做什么。即仅将其用于包含在引号中的值(但用于_every_这样的值),则在客户端(PHP)以及服务器/连接端(mysql)上设置正确的编码。有很多地方你可能会错过一些小东西,并再次被搞砸。 – knittl 2012-03-04 08:11:48

+0

此功能不是为了防止任何注射。去图 – 2012-03-04 10:34:04

+0

谢谢你的评论,我已经用一些信息更新了我的答案。 @ Col.Shrapnel为什么这个函数不是用来防止SQL注入的?从php.net:'如果这个函数不用于转义数据,这个查询就容易受到SQL注入攻击。“#: – 2012-03-04 12:35:40

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); 
+0

我明显输入太慢! – TerryProbert 2012-03-04 08:10:45

相关问题