Подтвердить что ты не робот

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

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

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

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

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

  • trim()
  • htmlentities($comment, ENT_NOQUOTES)
  • mysqli_real_escape_string()
  • nl2br()

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

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

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

4b9b3361

Ответ 1

Сначала сохраните текст логичным и чистым:

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> ..., чтобы ввести всевозможные гадости в вашу веб-страницу и, возможно, всю вашу систему.

Ответ 2

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

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

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

  • для больших баз данных они значительно ускорят (как и 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 для integer и 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-символы.

Ответ 3

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

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

Ответ 4

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

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

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

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

Ответ 5

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