Вход пользователя с одним запросом и солью пользователя для каждого пользователя

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

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

Поэтому, чтобы избежать двух запросов (1, чтобы получить соль, а другой – для проверки входных учетных данных), я решил получить соль И хешированный пароль в одном запросе на основе введенного имени пользователя. Что-то вроде

SELECT users.salt, users.password FROM users WHERE username = ?' 

а затем в файле serveride code (PHP) я конкатенирую соль с введенным паролем, хеширую его и сравниваю с паролем, уже взятым из базы данных.

Если это не ясно, я думаю, что ключевое различие заключается в том, что в последнем методе я проверяю учетные данные в PHP, прежде чем это было сделано в базе данных.

Существуют ли какие-либо недостатки этого метода в плане безопасности или иным образом

Вы можете выполнить это в одном запросе следующим образом:

 SELECT SHA1(CONCAT(users.salt, "password-input")) = users.passwordhash WHERE username = "username-input" 

… и который является сервером в «в серверном коде (PHP)»? Я родом из мира, где СУБД является сервером, а все остальное – клиентом. Я подозреваю, что вы смотрите на веб-сервер как «серверную» и СУБД как отдельную штуковину, не обязательно как сам сервер. Хорошо, такова теория относительности точек зрения. (И не заставляйте меня запускать серверы X11 против клиентов!)

Да, разумно просто собирать соль и соленый, хешированный пароль для имени пользователя за одну операцию, а затем генерировать результат SHA предоставленного пароля и соли в PHP, сравнивая его с полученным значением хэшированного пароля. Это даже означает, что пароль не перемещается с PHP на сервер базы данных, поэтому не имеет значения, зашифровано ли это сообщение или нет (в ситуации, когда PHP и СУБД находятся не на одном компьютере). Он также выгружает вычисления из СУБД в PHP; является ли это преимуществом, зависит от относительной рабочей нагрузки PHP и СУБД.

Как указывает другой ответ, можно получить ответ, отправив предоставленный пользователем пароль в СУБД и используя СУБД для вычисления хэшей. Остерегайтесь просто цитирования ввода пользователя – избегайте его, чтобы предотвратить инъекцию SQL . Это потенциально предоставляет пароль для отслеживания при поездке с PHP на СУБД. Насколько это важно, зависит от вашей инфраструктуры.

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

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

Я не вижу никаких недостатков. «gahooa» дал отличный ответ. Он перенесет стоимость обработки с вашего веб-сервера на ваш сервер базы данных, но это только вопрос для вас, какой из них лучше подходит для загрузки.