Замена функций mysql_ * на PDO и подготовленные операторы

Я всегда выполнял простое подключение 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 за то, что я открываю глаза на что-то необычное. Трудно выбрать лучший ответ, но я думаю, что полковник Шрапнель заслуживает его, так как все в значительной степени покрыто, даже если перейти к другим массивам с пользовательскими библиотеками, о которых я не знал!

Но спасибо всем вам :)

10
задан Peter O. 3 February 2013 в 04:08
поделиться