MySQL код для вставки имени пользователя и пароля в таблицу, если в этой таблице есть лицензионный ключ - PullRequest
0 голосов
/ 06 мая 2018

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

Это код, который у меня не работает:

"IF EXISTS (SELECT * FROM login WHERE LK = "+reglicenceEntry.Text()+") THEN 
 INSERT INTO `login` (`Username`, `Password`, `LK`) VALUES 
 ('"+regusernameEntry.Text()+"', '"+regpasswordEntry.Text()+"', ''); "

Это ошибка Голанга:

Ошибка 1064: у вас ошибка в синтаксисе SQL; проверьте руководство, соответствующее вашей версии сервера MySQL, на предмет правильного синтаксиса, который можно использовать рядом с «ЕСЛИ СУЩЕСТВУЕТ (ВЫБЕРИТЕ * ОТ РЕГИСТРАЦИИ, ГДЕ LK = '5qp515YHXEmSDzwqgoJh'), ТО ВСТАВЬТЕ В» в строке 1

Большое спасибо!

1 Ответ

0 голосов
/ 06 мая 2018

Синтаксис MySQL не поддерживает конструкции IF...THEN, кроме как в хранимых подпрограммах, триггерах и событиях. Смотри https://dev.mysql.com/doc/refman/8.0/en/sql-syntax-compound-statements.html

Я предлагаю альтернативное решение для вашего кода:

INSERT INTO `login` (`Username`, `Password`, `LK`)
SELECT ?, ?, ''
FROM `login`
WHERE `LK` = ?
LIMIT 1

Если ваша таблица входа в систему не имеет значения LK, приведенный выше SELECT вернет 0 строк, поэтому ничего не вставит.

Если ваша таблица входа в систему имеет значение LK, приведенное выше SELECT вернет хотя бы 1 строку (и я ограничу ее 1), поэтому она вставит строку. Вставляемая строка состоит из вашего имени пользователя и пароля, а также пустой строки для LK.

Я показал использование заполнителей параметров. Вы должны использовать параметры в SQL вместо объединения переменных в ваш запрос. Это хорошая практика, чтобы избежать случайного внедрения SQL. См. http://go -database-sql.org / подготовленный.html для примеров.


Цель использования параметров - избежать проблем с внедрением SQL. См. Мой ответ на Что такое SQL-инъекция? для объяснения SQL-инъекции.

Или моя презентация Мифы и ошибки SQL-инъекций (или видео на YouTube ).

При использовании параметров вы делаете два шага.

  • Первый шаг для подготовки запроса с заполнителями (?), в котором в противном случае вы могли бы объединить переменные в запрос SQL.
  • Второй шаг - выполнить подготовленный запрос, и это время, когда вы передаете переменные для заполнения заполнителей.

Смысл в том, чтобы держать переменные отдельно от вашего запроса, поэтому, если в переменной есть что-то, что может непреднамеренно изменить ваш синтаксис SQL (например, несбалансированные кавычки), оно никогда не объединяется с SQL. После того, как вы выполните подготовку, SQL уже проанализирован сервером MySQL, и после этого невозможно изменить синтаксис.

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

Таким образом, динамические части запроса - ваши переменные - хранятся отдельно от синтаксиса SQL, и вы избегаете проблем с внедрением SQL.

Для вашей задачи, описанной в вашем вопросе, это выглядело бы примерно так (я не проверял этот код Go, но он должен поставить вас на правильный путь).

stmt, err := tx.Prepare("INSERT INTO `login` (`Username`, `Password`, `LK`) SELECT ?, ?, '' FROM `login` WHERE `LK` = ? LIMIT 1")
if err != nil {
    log.Fatal(err)
}
defer stmt.Close()

_, err = stmt.Exec(regusernameEntry.Text(), regpasswordEntry.Text(), reglicenceEntry.Text())
if err != nil {
    log.Fatal(err)
}

Порядок параметров важен. Переменные, которые вы передаете в Exec(), должны быть в том же порядке, в котором заполнители ? появляются в вашем подготовленном операторе SQL. Они сопоставляются один за другим в том же порядке сервером MySQL.

Не ставьте кавычки вокруг заполнителей в подготовленном операторе SQL. Это будет работать как буквальная строка '?' в SQL. Используйте символ ? без кавычек для заполнителя. Когда он объединяется с MySQL на сервере, он будет работать так, как если бы вы поместили кавычки вокруг значения в виде строки, но без риска внедрения SQL, даже если это строковое значение содержит специальные символы.

Вот еще один сайт, который дает больше примеров кода: https://github.com/go-sql-driver/mysql/wiki/Examples

Функция Exec() предназначена для выполнения SQL без набора результатов, такого как INSERT, UPDATE, DELETE. В драйвере Go SQL есть другие функции, такие как Query() и QueryRow(), которые также принимают аргументы параметров. Вы бы использовали их, если ваш SQL возвращает набор результатов.

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