PHP « Каким методом лучше проверять валидность логина пользователя? PHP или SQL?
Все мы когда нибудь писали скрипт авторизации в системе. И как правило используют один из двух существующих методов:
1) PHP
Создаем запрос, который вынимает данные пользователя по переданному $id:
запрос будет выглядить как-то так -
/** * GeSHi (C) 2004 - 2007 Nigel McNie, 2007 - 2008 Benny Baumann * (http://qbnz.com/highlighter/ and http://geshi.org/) */ .sql.geshi_code {font-family:monospace;} .sql.geshi_code .imp {font-weight: bold; color: red;} .sql.geshi_code .kw1 {color: #993333; font-weight: bold;} .sql.geshi_code .co1 {color: #808080; font-style: italic;} .sql.geshi_code .co2 {color: #808080; font-style: italic;} .sql.geshi_code .coMULTI {color: #808080; font-style: italic;} .sql.geshi_code .es0 {color: #000099; font-weight: bold;} .sql.geshi_code .br0 {color: #66cc66;} .sql.geshi_code .sy0 {color: #66cc66;} .sql.geshi_code .st0 {color: #ff0000;} .sql.geshi_code .nu0 {color: #cc66cc;} .sql.geshi_code span.xtra { display:block; }
SELECT pass
FROM users
WHERE login = '$login'
Дальше мы сравниваем переданный $password с тем, который был вытащен в запросе. В случае если они одинаковы - пускаем пользователя в систему.
2) SQL
Все решается в самом запросе:
/** * GeSHi (C) 2004 - 2007 Nigel McNie, 2007 - 2008 Benny Baumann * (http://qbnz.com/highlighter/ and http://geshi.org/) */ .sql.geshi_code {font-family:monospace;} .sql.geshi_code .imp {font-weight: bold; color: red;} .sql.geshi_code .kw1 {color: #993333; font-weight: bold;} .sql.geshi_code .co1 {color: #808080; font-style: italic;} .sql.geshi_code .co2 {color: #808080; font-style: italic;} .sql.geshi_code .coMULTI {color: #808080; font-style: italic;} .sql.geshi_code .es0 {color: #000099; font-weight: bold;} .sql.geshi_code .br0 {color: #66cc66;} .sql.geshi_code .sy0 {color: #66cc66;} .sql.geshi_code .st0 {color: #ff0000;} .sql.geshi_code .nu0 {color: #cc66cc;} .sql.geshi_code span.xtra { display:block; }
SELECT COUNT(1)
FROM users
WHERE name = '$name'
AND password = '$pass'
И дальше остается просто проверить - выполнился ли запрос и если он вернул еденичку, то пускаем юзера в систему.
Вопрос - какой метод на ваш взгляд предпочтительней и почему? Какие подводные камни вы видите в каждом из них?
Спасибо.
UPD. Для тех кто минусует и ищет в вопросе чтобы покритиковать:
- все примеры условные!
- меня не волнует то, как нужно что-то экранировать шифровать и так далее, повторюсь, примеры написаны упрощенные для ясности
UPD 2 Думал, что на этом ресурсе умные люди. Гики, которые умеют не только смотреть на код между текстом вопроса и искать в нем ошибки, а отвечать по существу. Критиковать и посылать учить мат часть стоит на форумах. Здесь - либо ты отвечаешь, либо молчишь.
UPD 3 Справедливость восторжествовала - хоть кто-то вник в суть вопроса и ответил по сабжу.
1 ответов
По сути, разница несущественная. При первом запросе надо обрабатывать две ситуации: когда БД вернула неправильный пароль и когда вообще ничего не вернула (логин указан неверно).
Во втором случае проще: либо пускаем, либо нет (о том, что логин правильный, а пароль нет, обычно все-равно молчим). Если вместо count запрашивать поля, можно сразу получить инфу о пользователе (ФИО, карму или что там надо показывать на странице). В случае неправильного пароля дополнительная информация не выбирается - чуть-чуть меньше нагрузки на БД. Поэтому я за 2-ой вариант.
О том что в БД пароли в открытом виде не хранят и сравнивают хеши, а также экранируют все что передается в запрос вы, наверное, знаете.
Первый способ мне больше нравится. Сразу можно профиль пользователя (без дополнительного запроса) получить. И потом можно использовать более сложное шифрование пароля. С солью и прочими прибамбасами.
Не вытащив соли пользователя, не получится сравнить хеш-пароля (а про хранение пароля в чистом виде... в общем за это надо отрубать руки). Поэтому сначала тягаем данные юзера, а затем, если эти данные нашлись - хешируем введёный пароль и проверяем его с хешем в базе. Вариант проверки на лету, т.е. прямо в SQL, вероятно, возможен на крутых СУБД, я не слышал ничего про нативные SQL функции шифрования в mySQL (хотя, возможно они есть).
Правда остаётся ещё вариант хранения соли в другом месте, к примеру, для пущей безопасности. Но это уже специф.случай )
Первый в помойку, я так могу указать любой юид и зайти под кем угодно и сделать что угодно.
Конечно второй, только шифруй пароли. И вместо каунта звездочку поставь, чтоб получить данные пользователя и положить их в сессию.
PS Рекомендую учить мат часть http://irbis-team.com/