Я всегда выполнял простое подключение 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
] или УДАЛИТЬ
с помощью 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), и ни один из них не упомянул об этом. Кажется очень странным, почему, просто избегая пользовательский ввод действительно небезопасен и, мягко говоря, не является хорошей практикой. Да, я знаю, что вы можете использовать Regex для решения этой проблемы, но все же я почти уверен, что этого недостаточно?
Насколько я понимаю, использование 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, например, я видел : переменная
и ?
как то, что, как мне кажется, известно как заполнители (извините, если это не так).
Но я думаю, что это примерно идея того, что нужно сделать, чтобы получить пользователя из базы данных
$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);
Но тогда я застрял на паре вещей, если бы переменная не была числом, а была строкой text, вы должны указать длину после 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 за то, что я открываю глаза на что-то необычное. Трудно выбрать лучший ответ, но я думаю, что полковник Шрапнель заслуживает его, так как все в значительной степени покрыто, даже если перейти к другим массивам с пользовательскими библиотеками, о которых я не знал!
Но спасибо всем вам :)