Входы пользователя, очистка и дезинфекция перед отправкой на db

Я искал много вопросов здесь, и я обнаружил, что они либо очень старые, либо предлагают использовать подготовленные заявления PDO, которые я не использую . Поэтому мне нужна ваша помощь, пожалуйста.

У меня есть небольшая дискуссия / чат, где пользователь отправляет сообщение с помощью <textarea>

Мне нужно очищать и фильтровать пользовательский ввод, чтобы он принимал только простые тексты (например, теги, теги html, никакие скрипты и т. Д.). Кроме того , важно разрешить разрывы строк.

Основываясь на моем чтении, я делаю следующее в следующем порядке:

  1. trim()
  2. htmlentities($comment, ENT_NOQUOTES)
  3. mysqli_real_escape_string()
  4. nl2br()

Является ли то, что я делаю, правильно? или я чего-то не хватает?

Также есть ли что-нибудь, что я должен делать, когда echo из данных из db?

действительно, цените вашу помощь и доброту

Во-первых, сохраните текст логичным и чистым:

 trim() -- OK htmlentities($comment, ENT_NOQUOTES) -- No; do later mysqli_real_escape_string() -- Yes; required by API nl2br() -- No; see below 

Логика этих рекомендаций: данные в базе данных должны быть просто данными. Не htmlentities, не br-tags. Но вы должны сделать escape_string для передачи данных с PHP на MySQL; эскалаты не будут сохранены.

Но … Это только средний шаг. Откуда взялись данные? Старые версии PHP пытаются «защитить» вас от добавления экранов и другого нежелательного файла, который работает нормально для HTML, но прикручивает MySQL. Выключите такое волшебное экранирование и получите необработанные данные.

Куда идут данные? Возможно, HTML? После того, как вы SELECTing данные из таблицы, сначала сделайте htmlentities() и (необязательно) nl2br() ;

Обратите внимание, что если вы ожидаете сохранить такие вещи, как <I> (для курсива), вы просите о неприятностях – больших неприятностях. Все, что нужно хакеру, это <script> ... ввести всевозможные гадости в вашу веб-страницу и, возможно, всю вашу систему.

У вас также есть другой вариант. Вы можете использовать подготовленные инструкции с mysqli

Им не очень сложно учиться и работать немного лучше, чем mysqli_real_escape_string() поскольку вам не нужно беспокоиться об экранировании каждой переменной, которая будет в вашем запросе. Они по своей природе «подготавливаются», прежде чем войти в базу данных. В этом есть и другие преимущества:

  1. вам не нужно addslashes() чтобы иметь возможность обрабатывать символы с апострофами и т. д.

  2. для больших баз данных они значительно ускорят ваши запросы (как PDO).

Вот как это сделать:

Вы подключаетесь к базе данных, создавая новый объект mysqli следующим образом:

 $conn = new mysqli($host, $username, $password, $dbname); if ($conn->connect_error) { die("Connection failed: " . $dbc->connect_error); } 

Затем вы хотите преобразовать переменные из своей формы.

Скажем, у вас есть поле формы:

 <input type="text" name="var1"> 

вы можете использовать htmlentities и обрезать вместе так и создать переменную $var1 :

 $var1 = htmlentities(trim($_POST['var1'])); 

Затем вы можете создать свою транзакцию следующим образом:

 $stmt= $conn->prepare("insert into tablename (key1, key2) values (?,?)"); $stmt->bind_param("is",$var1, $var2); $stmt->execute(); $stmt->close(); 

Это в основном это. Вы делаете запрос так же, как обычно, но вместо этого используете ? заполнители, присваивая тип данных (выше i для целого числа и s для строки), а затем связывают их с вашими заполнителями в запросе.

Это в основном это.

если вы хотите сделать это с помощью select с переменной, вы используете обычный синтаксис выбора и аналогичным образом с помощью ? с переменной, а затем связать ее. Затем вы можете легко привязать свои результаты к переменным (при условии, что var3 является целым числом):

 $stmt= $conn->prepare("select var1, var2 from tablename where var3 = ?"); $stmt = bind_param("i", $var3); $stmt->bind_result($var1, $var2); $stmt->execute(); $stmt->close() 

и затем вы можете получить свои переменные, используя это

 $stmt->fetch(); 

или если ваш запрос возвращает несколько строк

 while ($stmt->fetch() { echo $var1 . $var2; } 

nl2br() используется для вывода, вам не нужно беспокоиться о вводе; он может быть сохранен в базе данных как \n , и когда вам это нужно, он выплевывает его как разрывы. Если одной из этих переменных нужны новые строки, превращенные в теги <br/> , вы можете, как вы предлагаете использовать nl2br() для переменных (обратите внимание, что это не добавляет безопасности, но, как вы сказали, вам это нужно), так

 echo nl2br($var1, false); 

вы также можете использовать trim() и htmlentities() для этого, если он отражается, скажем, в поле ввода формы, и вы не хотите, чтобы ваша форма прерывалась, если на выходе есть html-символы.

Ваш вопрос может привести меня к созданию полного проекта с множеством функций;) lol

Прежде чем мы начнем с этапов, нам нужна фиктивная (тестовая) база данных для этого сценария. Мы вызываем чат с базой данных с таблицей chat. Вы можете просто создать его, выполнив следующий SQL-запрос в тестовой среде MySQL:

 CREATE TABLE `chat` ( `id` INT(11) NOT NULL AUTO_INCREMENT, `msg` VARCHAR(200) NOT NULL DEFAULT '0', `user_id` INT(11) NULL DEFAULT '0', PRIMARY KEY (`id`) ) ENGINE=InnoDB ; 

Теперь вы можете пойти в голову и выполнить следующие шаги:

Шаг 1. Создайте папку проекта на своем веб-сервере. Создайте соединение с базой данных на основе PDO и назовите его dbConnect.inc.php :

 <?php // check if PDO driver not available if (!defined('PDO::ATTR_DRIVER_NAME')) echo 'PDO driver unavailable <br />'; // database configuration $dbHost = "localhost"; $dbPort = "3306"; $dbName = "chatbox"; $dbUser = "root"; $dbPass = ""; $strDSN = "mysql:host=$dbHost:$dbPort;dbname=$dbName"; // database connection try { $dbConn = new PDO($strDSN, $dbUser, $dbPass); //Activate following line to view all error messages $dbConn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); } catch (PDOException $e) { die("Could not connect to the database $dbName, error info: <br />" . $e->getMessage()); exit(); } 

Я проверю это, прежде чем перейти к следующему шагу. Btw подготовленный метод не требует mysqli_real_escape_string() .

Я использовал PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION вместо операторов if, этот метод даст вам полезные сведения об ошибке при разработке проекта. Вы узнаете, какой метод более практичен для получения сообщения об ошибке во время процесса разработки проекта.

Шаг 2. Создайте файл- filter.inc.php :

 <?php // filter for input function filterInput($content) { $content = trim($content); $content = stripslashes($content); return $content; } //filter for viewing data function filterOutput($content) { $content = htmlentities($content, ENT_NOQUOTES); $content = nl2br($content, false); return $content; } 

Этот файл содержит функцию filterInput для дезинфекции или фильтрации вашего входного содержимого для комментариев или других входов. И filterOutput которые влияют на просмотр данных.

Все, в зависимости от вашей стратегии и того, что вам нужно, например, если вам нужно разрешить людям отправлять URL-адрес или адрес электронной почты, следует указать URL-адрес и электронную почту, чтобы активировать ссылку или просматривать только текст и т. Д. Таким образом вы можете определить, какой фильтр следует использовать для вашего контента вход и какой фильтр следует использовать для вывода контента.

Вы можете добавлять или удалять дополнительные функции для функций. Есть много возможностей для ввода и вывода текста, вы можете протестировать их по отдельности и оценить его, а также расширить функцию фильтра или создать свою собственную функцию.

Заключительный шаг 3: Теперь мы помещаем головоломки в наш файл index.php :

 <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title>Chat box</title> </head> <body> <?php include './dbConnect.inc.php'; ?> <?php include './filter.inc.php'; ?> <h1>Chat box</h1> <p> <?php // this is dummy user id, but use the id over user id when login or the way you want // this is only example $user_id = 1; if (isset($_POST["msg"])) { $msg = filterInput($_POST["msg"]); $sql = "INSERT INTO chat " . "(msg, user_id) " . "VALUES " . "(:msg, :user_id)"; $stmt = $dbConn->prepare($sql); $fieldsArr = [':msg' => $msg, ':user_id' => $user_id]; $stmt->execute($fieldsArr) // refresh page after insert header("Location: " . $_SERVER['REQUEST_URI']); } ?> <form action="index.php" method="post"> <textarea name="msg" id="msg" required></textarea> <input name="submit" type="submit"> </form> </p> <p>Comments</p> <p> <?php $sql = "SELECT * FROM chat WHERE user_id = (:user_id);"; $stmt = $dbConn->prepare($sql); $fieldsArr = [':user_id' => $user_id]; $stmt->execute($fieldsArr) while ($result = $stmt->fetch()) echo "<h3>" . filterOutput($result['msg']) . "</h3>"; $dbConn = null; ?> </p> </body> </html> 

Это демонстрирует, как все работает. У вас есть insert, select statement в качестве примера и функции фильтрации. Вы можете делать тесты, расширять их так, как вам нравится, или развивать свой собственный проект.

Вот скриншот из примера чата, который я сделал: введите описание изображения здесь

filter_input может быть другим, который вы ищете. Это может сэкономить вам часы от написания кода санитарии и проверки. Конечно, он не охватывает каждый отдельный случай, но этого достаточно, чтобы вы могли больше сосредоточиться на конкретном файле фильтрации / проверки.

Хотя настоятельно рекомендуется использовать подготовленные инструкции с PDO / mysqli. Но иногда преобразовать весь проект в хвост проекта не так-то просто. Вы должны изучить PDO / mysqli для своего следующего проекта.

 $comment = filter_input(INPUT_POST, 'comment', FILTER_SANITIZE_STRING); 

Для вас есть разные типы фильтров . Вы можете выбрать в зависимости от ваших потребностей. Вы также можете использовать filter_has_var для проверки набора переменных.

Ваш код выглядит хорошо, если вы не хотите готовить заявления, тогда побег – это лучшая вещь. И когда вы эхом, это должно быть просто, это всего лишь текст.