SQL запрос в php с вводом из html выпадающего - PullRequest
0 голосов
/ 15 марта 2020

Хорошо, я пытаюсь создать инструмент оценки запросов для проекта. Я получаю пользовательский ввод как переменную php и использую его в своем запросе, так что пользователь как будто отправляет запрос. Я использую mysqli

В настоящее время я делаю это с моим запросом

$sql = "SELECT * FROM `idk` where  `alias` = '".$s."'"; 

Я получаю значения из формы ниже

$s = $_GET['val'];
<select name="selector" id = "selector">
        <option value="">Select a criteria:</option>
        <option value="0">id</option>
        <option value="1">name</option>
        <option value="2">email</option>
        <option value="3">alias</option>
        <option value="4">position</option>

I Мне интересно, могу ли я добавить пользовательский ввод для условия условия where (=,! =) и получить его так, как будто я получаю значение для столбца вместо жесткого его кодирования.

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

1 Ответ

0 голосов
/ 17 марта 2020

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

Если у вас есть ввод для пользовательского значения:

<input type="number" name="age" value="" />

, добавьте поле выбора перед ним:

<select name="age_comparison">
    <option value="equal">equal to</option>
    <option value="not_equal">not equal to</option>
    <option value="less_than">less than</option>
    <option value="greater_than">greater than</option>
</select>
<input type="number" name="age" value="" />

Примечание : позиция не относится к обработке - вообще. Я просто думаю, что удобнее, если пользователи читают вашу страницу так же, как текст в реальной жизни. Это означает, что когда ввод вводится позже, он будет читаться как «возраст больше, чем X», что читается лучше, чем «возраст Х, больше, чем», если вы вводите ввод первым.

По той же причине (лучший пользовательский опыт ), Я склонен обозначать варианты чем-то, что больше похоже на человека, следовательно, «равно» вместо просто «равно». Но я пропустил его в значениях параметров, поскольку он не добавляет никакой ценной информации в код («равно» рассказывает всю историю как значение параметра).

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

if (isset($_GET['age'])) {
    $age = $_GET['age'];
}
if (isset($_GET['age_comparison'])) {
    switch ($_GET['age_comparison']) {
        case 'equal':
            $ageComparison = '=';
            break;
        case 'not_equal':
            $ageComparison = '!=';
            break;
        case 'less_than':
            $ageComparison = '<';
            break;
        case 'greater_than':
            $ageComparison = '>';
            break;
    }
}
// if we have all the parameters, we can query the database
if (isset($age) && isset($ageComparison)) {
    // the following line is very unsafe - we'll be on that in a minute
    $queryString = 'SELECT * FROM students WHERE age '.$ageComparison.$age;
    ...

Примечание : я использовал $_GET, потому что вы использовали его в своем вопросе. Если в вашей форме будет несколько параметров, я советую вам использовать метод post и избегать добавления целой группы параметров в URL вашей страницы. Значения вашей формы будут находиться под теми же ключами, только в переменной $_POST. Кроме того, когда вы используете post, достаточно определить, задано ли имя отправки - если это так, то гарантированно будут присутствовать и остальные входные данные из той же формы. С get вы должны проверить каждый параметр индивидуально.

Так что у вас есть. Запрос с операторами сравнения переменных.

НО

Мы еще не закончили. Есть некоторые плохие практики, которые нужно отбросить, и некоторые полезные практики, которые можно найти по пути.

Прежде всего, никогда не создавайте запросы, напрямую вставляя параметры:

$sql = "SELECT * FROM `idk` where  `alias` = '".$s."'";

Это делает вас более широкими открыть для SQL инъекция . Вместо этого вы должны использовать подготовленные заявления . Подготовленные операторы имеют встроенные механизмы защиты, а также заботятся обо всех ваших потребностях в цитировании (то есть вам не нужно вручную ставить отметки uote вокруг параметров, которые являются строками). Таким образом, вы делаете это так:

// the question mark means we'll be adding a parameter in that position
$queryString = 'SELECT * FROM students WHERE age '.$ageComparison.' ?';
// here I assume you have mysqli statement ready
// you can see an example about creating one in the link about prepared statements
$statement->prepare($queryString);
$statement->bindParam('i', $age);

Вы можете сказать: «Но подождите минуту ! Вы только что добавили оператор сравнения напрямую ! Разве это не опасно? ?» - нет, потому что это не пришло непосредственно от пользователя. Мы определили его значение в операторе switch, что означает, что мы взяли пользовательский ввод (который может быть скомпрометирован) и превратили его в значение, которое мы контролируем . Пользователь не может решить, что выходит из оператора switch, мы можем. Следовательно, безопасно напрямую связать его в строку запроса, потому что мы знаем, что мы определили некоторые безопасные значения.

Говоря об операторе switch, в нем тоже есть улучшение. Что если мы добавим еще один параметр в select, но мы забудем добавить его в оператор switch? Или злонамеренный пользователь ставит под угрозу ценность отправляемой опции? В результате мы получим ошибку, так как в этом случае никакие случаи в переключателе не будут сопоставлены (случай для значения за пределами 4, который мы поместили там, не определен), и, таким образом, переменная $ageComparison никогда не будет создана, и мы будем никогда не выполняйте запрос, потому что наше условие if не выполнится. Так как же это исправить? Мы добавляем регистр по умолчанию (по умолчанию выполняется, когда ни один из случаев не совпадает):

// remainder of statement cut for length
    ...
    case 'greater_than':
        $queryComparison = '>';
        break;
    default:
        throw new Exception('Unsupported value for age comparison: '.$ageComparison);
}

Исключения останавливают выполнение, если не обрабатывается (правильный термин - catch ), но я буду предоставьте это вам, если вы будете sh, чтобы исследовать этот топи c самостоятельно (кажется, немного для новичка, плюс здесь уже довольно много текста).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...