Определите, какая часть (части) инструкции WHERE Завершилась с ошибкой

StackOverflow https://stackoverflow.com/questions/1412195

Вопрос

Допустим, у меня есть оператор SQL, подобный этому, который проверяет логин пользователя:

SELECT * FROM users 
WHERE username='test@example.com', password='abc123', expire_date>=NOW();

Есть ли в SQL способ конкретно определить, какие условия WHERE не выполняются, без необходимости разделять каждое условие на его собственный запрос и тестировать по отдельности?

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

Для своих целей я использую PHP / MySQL.

Это было полезно?

Решение 5

Вот что я придумал:

SELECT
  IF(mem_username='test@example.com','true','Error: Bad Username') AS mem_username,
  IF(mem_password ='abc123','true','Error: Bad Password') AS mem_password'
FROM MEMBERS
WHERE mem_username='test@example.com' AND mem_password='abc123'

Таким образом, я могу обнаружить в коде сообщения об ошибках, а затем отобразить их при необходимости.

ПРИМЕЧАНИЕ. Всем, кто ссылается на соображения безопасности в примере кода, спасибо за внимание. Тем не менее, это не настоящий производственный код, это был простой пример, демонстрирующий мой вопрос. Совершенно очевидно, что вы не должны хранить пароли в виде открытого текста, и что вы не должны давать пользователям конкретные сведения о том, почему не удается войти в систему.

Другие советы

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

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

Что касается вашего фактического вопроса (в отличие от результатов, которые вы ищете), нет способа получить эту информацию из предложения where. Самое близкое, что вы можете сделать, это что-то вроде:

SELECT *,
    CASE WHEN Password = 'asdf' THEN 1 ELSE 0 END AS IsPasswordMatch,
    CASE WHEN Expiration >= NOW() THEN 1 ELSE 0 END AS IsActiveAccount
FROM Users
WHERE Username = 'user'

В MySQL вы можете помещать логические выражения в список выбора. Булевы выражения оцениваются в целое число 1, если оно истинно, или в целое число 0, когда ложно.

SELECT password = 'abc123' AS is_authenticated,
       expire_date >= NOW() AS is_not_expired
FROM users
WHERE username='test@example.com';

note: Если вам нужно написать запрос, который работает с другими брендами СУБД, имейте в виду, что использование логических выражений не является стандартным. Используйте синтаксис CASE , опубликованный другими людьми.

PS: Это касается вашего вопроса, но я призываю вас не хранить пароли в открытом виде. Сохраните хэш-дайджест соленого пароля. См. Как соль пароля помогает против атаки с помощью радужного стола?

Нет, предложение where- применяется как блок, и используются различные методы, чтобы не нужно было сканировать все строки.Кроме того, как бы вы узнали, какая строка была нужной?

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

Редактировать Если вы действительно хотите отобразить это своему пользователю, то разделите свою логику на разные части:

  1. Проверка подлинности
    Экшен:Извлеките соответствующую строку пользователя из базы данных
    Результат:
    • Если такой строки не существует => недопустимая учетная запись
    • Если строка возвращена, перейдите к шагу 2.
  2. Проверка учетных данных
    Экшен:Сверьте сохраненные учетные данные (пароль, хэш пароля или зашифрованный пароль) с предоставленным паролем, обработанным таким же образом, как хранятся учетные данные.
    Результат:
    • Нет совпадения => Неверный пароль / учетные данные
    • Совпадение => Успешная попытка входа в систему
  3. Войти в систему пользователя
    Экшен:Добавление данных в сеанс и т.д.

Вероятно, вам просто нужно разделить части предложения where с помощью AND.

SELECT * FROM users 
WHERE username='test@example.com'
   And password='abc123'
   And expire_date>=NOW();
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top