我一直使用简单的连接方式mysql_connect
和 mysql_pconnect
:
$db = mysql_pconnect('*host*', '*user*', '*pass*');
if (!$db) {
echo("<strong>Error:</strong> Could not connect to the database!");
exit;
}
mysql_select_db('*database*');
我使用这个方法时,总是在进行查询之前使用简单的方法来转义任何数据,无论是INSERT
、SELECT
、UPDATE
还是DELETE
都会使用mysql_real_escape_string
。
$name = $_POST['name'];
$name = mysql_real_escape_string($name);
$sql = mysql_query("SELECT * FROM `users` WHERE (`name` = '$name')") or die(mysql_error());
现在我理解这是安全的,但只是在一定程度上!
它可以转义危险字符;然而,它仍然容易受到其他攻击的影响,这些攻击可能包含安全字符,但可能对显示数据或某些情况下的恶意修改或删除数据有害。
因此,我进行了一些搜索,并了解了PDO、MySQLi和预处理语句。是的,我可能太晚了,但我已经阅读了许多教程(如tizag、W3C、博客、Google搜索),没有一个提到过它们。这似乎非常奇怪,因为仅仅转义用户输入并不安全,至少不是好的实践。是的,我知道你可以使用正则表达式来解决它,但我确信那还不够?
据我了解,当变量由用户输入时,使用PDO /预处理语句是从数据库存储和检索数据的更安全方法。唯一的问题是,切换(特别是在之前编码方式/习惯上非常固执的情况下)有点困难。
现在我理解要使用PDO连接到我的数据库,我会使用
$hostname = '*host*';
$username = '*user*';
$password = '*pass*';
$database = '*database*'
$dbh = new PDO("mysql:host=$hostname;dbname=$database", $username, $password);
if ($dbh) {
echo 'Connected to database';
} else {
echo 'Could not connect to database';
}
现在,函数名称已经不同,因此我的mysql_query
,mysql_fetch_array
,mysql_num_rows
等都不再有效。所以我必须阅读/记住一堆新的东西,但这就是我感到困惑的地方。如果我想要从注册表单中插入数据,我该如何做到这一点,但主要是如何安全地进行操作?我想这就是准备好的语句的用处,但使用它们是否消除了使用像
mysql_real_escape_string
这样的东西的需要?我知道mysql_real_escape_string
需要通过mysql_connect
/mysql_pconnect
连接到数据库才能使用,所以现在我们不再使用任何一个,这个函数是否只会产生错误?我还看到了不同的PDO方法,例如,我看到了
:variable
和?
被称为占位符(如果我理解错了,请原谅我)。但我认为这大致上就是从数据库中提取用户所需做的事情。
$user_id = $_GET['id']; // For example from a URL query string
$stmt = $dbh->prepare("SELECT * FROM `users` WHERE `id` = :user_id");
$stmt->bindParam(':user_id', $user_id, PDO::PARAM_INT);
但是,我遇到了一些问题。如果变量不是数字而是一个文本字符串,你必须在 PDO:PARAM_STR
后给出一个长度(如果我没有搞错的话)。但是,如果用户输入的值是不确定的,每次都可能不同,那么如何指定长度呢?无论如何,据我所知,要显示数据,然后执行以下操作:
$stmt->execute();
$result = $stmt->fetchAll();
// Either
foreach($result as $row) {
echo $row['user_id'].'<br />';
echo $row['user_name'].'<br />';
echo $row['user_email'];
}
// Or
foreach($result as $row) {
$user_id = $row['user_id'];
$user_name = $row['user_name'];
$user_email = $row['user_email'];
}
echo("".$user_id."<br />".$user_name."<br />".$user_email."");
现在,这一切都安全吗?
如果我没错的话,比如插入数据会是相同的方式:
$username = $_POST['username'];
$email = $_POST['email'];
$stmt = $dbh->prepare("INSERT INTO `users` (username, email)
VALUES (:username, :email)");
$stmt->bindParam(':username, $username, PDO::PARAM_STR, ?_LENGTH_?);
$stmt->bindParam(':email, $email, PDO::PARAM_STR, ?_LENGTH_?);
$stmt->execute();
这样做可行吗?而且也安全吗?如果正确,那么?_LENGTH_?
应该填什么值?我是否完全搞错了?
更新
到目前为止,我收到的答复非常有帮助,感谢你们!每个人都得到了一个+1,因为你们让我看到了一些不同的东西。很难选择最佳答案,但我认为Col. Shrapnel应该得到它,因为几乎所有东西都被涵盖了,甚至还涉及到使用自定义库的其他数组,这是我不知道的!
但感谢你们所有人:)