|
Модераторы: skyboy, MoLeX, Aliance, ksnk |
|
baLamooot |
|
||||
Шустрый Профиль Группа: Участник Сообщений: 101 Регистрация: 29.8.2004 Репутация: нет Всего: нет |
Приветы.
Встала такая проблема. Есть сайт с регистрацией, логином и сменой пароля. Итак, код (чисто чтобы обрисовать проблему, а не подробный листинг того нагромождения кода, который имеется)
Т.е. механизм прост до безобразия: из формы отправляются данные, принимаются скриптом, скрипт сверяет post-данные с тем, что хранится в БД и при успехе сравнения записывает данные в куки и сессии, чтобы потом сравнивать данные в куках с сессией, а не лазить в БД и при условии, что проверка проходит гладко, пользователю показывается секретный контент. Чтобы поменять пароль надо сделать следующее:
Так вот теперь к сути. Допустим, одна и та же учетка открыта в 2 различных браузерах (а может и на разных машинах), т.е. на сервере в папке сессий существуют 2 файла с сессиями от 2-х браузеров. В том браузере, с которого я менял пароль, удаляются куки и обнуляются сессии, т.е. теперь по старому паролю к секретным данным не пробиться. НО, во втором браузере остаются старые куки и сам браузер привязан к той сессии, где еще хранится старый пароль. Т.е. не смотря на то, что в базе пароль и куки новые, пользователь (потенциальный злоумышленник) все еще может просматривать запрещенные данные до истечения сессии (session.gc_maxlifetime + время когда гарбедж коллектор почешится чтобы удалить данные) или $_COOKIE['PHPSESSID'] (в зависимости от того, кто из них первый сдохнет). Такой расклад меня не очень устраивает. Решение я вижу в том, чтобы как-то удалить остальные сессии данной учетки, но не вижу подобной возможности. Возможно, я неправ и это делается как-то иначе, но на удаление куков надежды мало (их можно контролировать на стороне клиента). Если можете подтолкнуть в нужном направлении, дать совет или кинуть ссылкой в правильную статью, буду весьма благодарен. Если это возможно, интересует именно решение на чистом php, т.е. без кэширования данных о пользователе на стороне сервера куда-нибудь в memcached с информацией, поменялся ли пароль или нет. Т.е. интересует универсальное средство вне зависимости от дополнительных модулей php. Заранее спасибо. Это сообщение отредактировал(а) baLamooot - 13.4.2013, 17:10 --------------------
Я не спятил, это мир сошел с ума |
||||
|
|||||
Sanchezzz |
|
|||
Эксперт Профиль Группа: Завсегдатай Сообщений: 1670 Регистрация: 19.11.2006 Где: Voronezh Репутация: 41 Всего: 60 |
Можно переопределить механизм хранения сессий session_set_save_handler
Или Делаем таблицу в БД или любом другом быстром key=value для чтения хранилише. user_id, sid имя файла сессии При авторизации проверяем в таблице свой user_id под которым авторизовались sid это session_id имя файла который нужно удалить . Удалили записываем следом в это жу таблицу текущий session_id. Тот пользователь который был авторизован его выкинет автоматом так как файл сессии удалили. При session_set_save_handler + БД например Sqlite:memory + все log_off можно контролировать все сессии и через админту тыкать и дисконектить пользователей. Еще через ini_set можно указать папку другую папку для сессий. -------------------- Понравился ответ "+" по репе, не забываем закрывать тему, заказы в LS. |
|||
|
||||
Arantir |
|
|||
Рыбак без удочки Профиль Группа: Участник Сообщений: 960 Регистрация: 18.11.2012 Репутация: 16 Всего: 55 |
Ну, для начала, пара вопросов:
А целесообразность этого какая? Это уже экономия на спичках... Вы сэкономили 0.0001 секунды ценой понижения безопасности. Зачем вы храните одни и те же данные в куках и в сессии одновременно? Вы даете злоумышленнику видимость дырки, а потом обламываете его проверкой идентичности данных? В чем вообще смысл этого? Эти 2 поля, которые в куках, вами, по видимому, вообще нигде больше не используются, так как вы берете их из сессии. --- Файлы сессий можно прочитать в любое время. Они сериализованы обычным способ и их можно быстро превратить в массив с помощью unserialize. В PHP даже есть функция, позволяющая получить текущий путь к папке сессий. -------------------- interface Жопа { // ATTENTION: has to be implemented by every class of the project for proper project work } |
|||
|
||||
Sanchezzz |
|
|||
Эксперт Профиль Группа: Завсегдатай Сообщений: 1670 Регистрация: 19.11.2006 Где: Voronezh Репутация: 41 Всего: 60 |
Подправлю насчет стерилизации сессии не получится просто так взять и все данные сессии и десерилизовать точно также как и серилизовать.
Строка похоже на серилизованную но немного отличается. Upd 1 Для десерилизаци сессии можно использовать след код, может кому то пригодится.
Это сообщение отредактировал(а) Sanchezzz - 13.4.2013, 19:06 -------------------- Понравился ответ "+" по репе, не забываем закрывать тему, заказы в LS. |
|||
|
||||
Arantir |
|
|||
Рыбак без удочки Профиль Группа: Участник Сообщений: 960 Регистрация: 18.11.2012 Репутация: 16 Всего: 55 |
Да, действительно. Хотя есть много готовых решений (в любом случае строка в читабельном виде и к ней можно сложить парсер вручную).
Но я бы вообще посоветовал добавить один запрос в БД с проверкой логина и пароля (такой же, как при входе). имхо, проверка логина/пароля при любом важном действии должна присутствовать о обязательном порядке. Сессия лишь освобождает пользователя от постоянного ввода логина и пароля. При этом можно не беспокоится о старых сессиях, какими старыми бы они не были, так как в каждый отдельный момент времени доступ предоставляется исключительно по текущему логину и паролю. -------------------- interface Жопа { // ATTENTION: has to be implemented by every class of the project for proper project work } |
|||
|
||||
baLamooot |
|
|||
Шустрый Профиль Группа: Участник Сообщений: 101 Регистрация: 29.8.2004 Репутация: нет Всего: нет |
Как понимаю, идея состоит в том, что основное действие завязано вокруг контроля сессий на более низком уровне (т.е. контролировать сами файлы сессий), так? То же самое касается и переопределения механизма хранения. В принципе я тоже ходил вокруг этой идеи, но не нравится вмешательство в сессии, т.е. удалять файлы сессий вручную. В веб-программировании это считается нормальной практикой или просто обходной маневр для данного случая? Второй предложенный вами вариант мне больше нравится, но опять приходится дергать БД (или другое хранилище) при каждом запросе. Хотя может в этом больше смысла, поскольку работает гибче, чем файлы сессий. Но тут встает очередная проблема: избавление от истекших sid-ов. Т.е. тут опять нужно "внешнее" для php решение, cron или что-то подобное. Или очищать список истекших при кажом запросе к сайту (что внесет излишнюю нагрузку). Я правильно понял идею?
Обращений к БД и без того будет хватать, так что для начала я просто снижаю нагрузку на нее. Пускай и на спичках, но при большом кол-ве пользователей может сказаться. Ну данные одинаковые, но на разных "эндах" (фронт и бэк). Для сверки при повторном заходе на сайт после истечении сессии. Тот скрипт сверху я привел только для описания проблемы. Не очень понял конечную идею. Вы предлагаете при смене пароля перерывать все файлы сессий в поисках файлов с нужной учеткой? --------------------
Я не спятил, это мир сошел с ума |
|||
|
||||
Arantir |
|
||||
Рыбак без удочки Профиль Группа: Участник Сообщений: 960 Регистрация: 18.11.2012 Репутация: 16 Всего: 55 |
Ответ как бы сам напрашивается... Но, вообще-то, я предлагаю просто сделать существование "устаревших" сессий невозможным. Смахивает на оправдания новичков... Сейчас у вас сессию вообще данные в БД не колышут. Вы можете хоть удалить пользователя напрямую из БД, а сессия и все права доступа останутся. Чтобы это предупредить, вам придется писать собственный механизм обеспечения актуальности сессий. Чтобы сессии изменялись/удалялись при любом, влияющем на авторизацию, действии, таком как смена пароля/логина, удаление пользователя и т.п. И производить подобные действия для сохранения безопасности можно будет только через созданный вами же интерфейс. Но в любом случае останется возможность что-то изменять напрямую из БД, даже не злоумышленником, а администраторами, пусть даже случайно, но вдруг... Устраняя прямую связь сессии и записи в БД вы создаете фантома, призрака пользователя, а не самого пользователя. И вам придется очень постараться, что за этими фантомами уследить. Хотя на этом этапе становится спорной целесообразность данного пути, как в объеме работы программиста, так и в затрачиваемых на его работу ресурсах. -------------------- interface Жопа { // ATTENTION: has to be implemented by every class of the project for proper project work } |
||||
|
|||||
Sanchezzz |
|
|||
Эксперт Профиль Группа: Завсегдатай Сообщений: 1670 Регистрация: 19.11.2006 Где: Voronezh Репутация: 41 Всего: 60 |
Переопределение механизма хранения сессии нормальная практика когда нужно снизить нагрузку на диск при очень большой посещаемости. В данной задачи это будет лишния трата времени.
Постоянных запросов к базе не будет, только при авторизации проверка. Сессия на мой взгляд нужна для неважных данных например для хранении user_id или одноразового токена. -------------------- Понравился ответ "+" по репе, не забываем закрывать тему, заказы в LS. |
|||
|
||||
baLamooot |
|
||||
Шустрый Профиль Группа: Участник Сообщений: 101 Регистрация: 29.8.2004 Репутация: нет Всего: нет |
Не спорю, веб-программированием не занимался довольно давно. Так что можно сказать, что мой уровень уже снова снизился до новичка. Так что от разумных советов не отказываюсь, все принимаю к сведению. Sanchezzz, иными словами, вы подразумеваете, что логично создать для авторизации 2 таблицы: 1) пользователи, где хранятся регистрационные данные, например, так
2) сессии, где хранятся данные по текущим сессиям.
И как я понял общую схему. Пользователь логинится, в куки идет хэш пароля и логин, в сессию - id пользователя и случайно сгенерированный сид, в таблицу sessions - id пользователя и sid (те же, что и в сессии). При каждом запросе делается проверка, соответствуют ли сид и user_id из сессии, одноименным поляв в таблице sessions. Если да, значит есть доступ, продолжаем серфить. Если нет, из куков достаем пароль и логин и браузер сам пытается залогиниться по новой. Если меняем регистрационные данные - удаляем из sessions всех сидов, принадлежащих данному user_id и тот сид, который в данный момент привязан к определенному браузеру не имеет никакого значению, поскольку ему уже ничего не соответствует. Правильно я понимаю? Если да, то все же что делать с устаревшими sid-ами? Вешать на крон скрипт для удаления всех записей из sessions с session_start_time < какого-то определенного времени (session_start_time тогда надо будет добавить)? Или удалять sid-ов при каждом залогинивании (или при восстановлении доступа из куков), чтобы каждый пользователь в один момент времени мог иметь только один sid? --------------------
Я не спятил, это мир сошел с ума |
||||
|
|||||
Arantir |
|
|||
Рыбак без удочки Профиль Группа: Участник Сообщений: 960 Регистрация: 18.11.2012 Репутация: 16 Всего: 55 |
Надо сказать, что хранить логин в куках ради "когда кончится сессия" нет смысла. Сессия обеспечивается теми же куками — в куках хранится id сессии. Поставить время истечения этой куки можно точно так же, как для кук логина/пароля (например, год на 2020-й). Посмотрите на куки того же гугла, к примеру.
Пользователь логинится на сайте, и получает от сервера PHPSESSID. Логин и хеш пароля заносятся в текущую сессию пользователя. При посещении страницы, в случае наличия сессии, делается запрос в бд к таблице пользователей на существование такого логина с таким хешем пароля. Если запись существует — пропускаем. Если нет — session_destroy(). При смене пароля все старые сессии оказываются в пролёте. А об остальных сессиях позаботится сам php. -------------------- interface Жопа { // ATTENTION: has to be implemented by every class of the project for proper project work } |
|||
|
||||
cia |
|
|||
Бывалый Профиль Группа: Участник Сообщений: 207 Регистрация: 15.1.2007 Репутация: 4 Всего: 4 |
А чем не устраивает классический механизм:
Пользователь заходит на сайт, на какой-то странице вводит логин/пароль (берётся из базы данных), затем в сессию кладётся ид и логин (если он вообще нужен, например чтобы написать: "привет, user1 (выйти)". Запрос к БД только один - при авторизации, дальнейшие манипуляция по ИД пользователя. И чем плохо то, что сессия продолжает жить после смены пароля? В сессии не хранится пароль, а только ид пользователя. Может быть нужно что-то типа "запомнить меня"? Тоже не вижу проблемы: в куке логин и пароль (его лучше зашифровать md5). При заходе на сайт по этому логину и паролю из базы данных берём ид пользователя (автоматическая авторизация). Если между сессиями пароль был сменен, то автоматическая авторизация завершится неудачей. Если же кто-то "угнал" кукисы и пытается войти с тем же ид сессии, то это работает лишь при одновременном подключении и пользователя и злоумышленника. И после смены пароля можно угнать новый ид сессии. Если уж хочется и от таких проблем избавиться, то можно между запросами раз в 1 минуту менять ид сессии. |
|||
|
||||
baLamooot |
|
||||
Шустрый Профиль Группа: Участник Сообщений: 101 Регистрация: 29.8.2004 Репутация: нет Всего: нет |
Да вроде не совсем тоже самое Добавляется возможность централизованного управления сидами, их можно удалять не прочесывая файлы сессий. Конечно, можно удалять и файлы сессий, но удаление 20 записей с сидами пользователя одним запросом не столь затратны, как 20 IO обращений к диску на удаление 20 файлов (тут уже счет идет явно не на спички). Либо я не так понял, либо получается так: пользователь заходит, сохраняется кука PHPSESSID, на сервере в сессии сохраняются пароль и логин, в течении данной сессии все нормально. Пользователь не разлогиниваясь выходит с сайта закрывает браузер. На следующий день заходит, кука на месте, но сессия с логином и поролем уже давно удалена сборщиком мусора, т.е. он снова разлогинен, никакой связи с предыдущей сессией нет, надо по новой вводить логин с паролем
Тем, что гипотетически смена пароля должна влиять сразу на аккаунт. Как с банковской картой: потерял, позвонил в теходдержку, заблокировали, с нее больше нельзя снять деньги. А по вашей схеме выходит так, что залогиненый (до смены пароля) пользователь после смены пароля с уже невалидным паролем продолжает серфить до следующего логина / автологина. Менять сид каждую минуту - зачем? Если не поменялся пароль, то смысла нет менять и сид, а к базе идет все то же одно обращение. Безопасность куков (за пределами скрипта) на стороне клиента я считаю заботой самого клиента. Хочет большой безопасности, тогда https и никаких автологинов. Это уже отдельный вопрос. --------------------
Я не спятил, это мир сошел с ума |
||||
|
|||||
Arantir |
|
|||
Рыбак без удочки Профиль Группа: Участник Сообщений: 960 Регистрация: 18.11.2012 Репутация: 16 Всего: 55 |
Перенастроить жизнь сессий не проблема. Разве что несколько лишних файлов сессий залежится (но сами по себе они не мешают как бы). А вообще, вы могли бы перенести сессии в базу данных (session_set_save_handler). Это несложно, всего создать 6 функций с соответствующими запросами (для php5.4+ даже есть удобный класс-интерфейс). БД работает получше файловой системы. Вам не надо будет особо беспокоится, будь сессий хоть десятки тысяч. В БД поиск по ключу очень быстрый и эффективный. А еще вы сможете воплотить свое желание с удобным выбором, поиском и удалением сессий по требованию (не дожидаясь сборщика мусора). В любом случае, постоянно хранить на стороне пользователя логин и пароль не очень-то безопаснее той же постоянно открытой сессии. -------------------- interface Жопа { // ATTENTION: has to be implemented by every class of the project for proper project work } |
|||
|
||||
baLamooot |
|
|||
Шустрый Профиль Группа: Участник Сообщений: 101 Регистрация: 29.8.2004 Репутация: нет Всего: нет |
Для онлайн-банкинга, интернетных платежных систем и других аккаунтов, требующих особой безопасности - наверно да. Но для типичных пользовательских акков, думаю, можно пожертвовать подобными мерами безопасности. Кроме того все же пароль на клиенте хранится захэшированный. А безопасность куков клиента, как я уже писал, - это уже забота клиента настроек безопасности сервера, программист тут должен позаботиться только об отсутствии дыр в коде. + еще можно продумать привязку куки к IP и браузеру (при отправки куки в браузер к ней цеплять хэш-токен составленный на основе инфы о браузере и IP), т.е. уже можно будет воспользоваться угнанными куками только с той же версии браузера и с того же IP, на которые были получены куки. Иными словами, насколько мне это видится, комфорт серфинга находится в прямой зависимости от безопасности: полная безопасность - это отсутствие автологина и https. Полный комфорт - это риск, что кто-то стянет и воспользуется куками и автологин. О переопределении механизма сохранения сессий я тоже подумаю. Может и имеет смысл для данного случая. В любом случае спасибо за высказанные мнения всем участникам обсуждения. На свой вопрос ответ я получил и при том не один, дело теперь за выбором --------------------
Я не спятил, это мир сошел с ума |
|||
|
||||
Правила форума "PHP" | |
|
Новичкам:
Важно:
Внимание:
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, IZ@TOP, skyboy, SamDark, MoLeX, awers. |
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | PHP: Общие вопросы | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |