#php #session #scope
Вопрос:
Одна вещь, которую я начал делать чаще в последнее время, — это извлекать некоторые данные в начале задачи и хранить их в $_SESSION[‘myDataForTheTask’].
Сейчас это кажется очень удобным, но я ничего не знаю о производительности, рисках безопасности или подобном, используя этот подход. Это то, что регулярно делают программисты с большим опытом, или это скорее любительская вещь?
Например:
if (!isset($_SESSION['dataentry']))
{
$query_taskinfo = "SELECT participationcode, modulearray, wavenum FROM mng_wave WHERE wave_id=" . mysql_real_escape_string($_GET['wave_id']);
$result_taskinfo = $db->query($query_taskinfo);
$row_taskinfo = $result_taskinfo->fetch_row();
$dataentry = array("pcode" => $row_taskinfo[0], "modules" => $row_taskinfo[1], "data_id" => 0, "wavenum" => $row_taskinfo[2], "prequest" => FALSE, "highlight" => array());
$_SESSION['dataentry'] = $dataentry;
}
Комментарии:
1. Ваш SQL-запрос уязвим для атак с использованием SQL-инъекций. Например, кто-то может поставить»? wave_id=wave_id», и запрос выберет все строки. (Хуже обстоит дело с запросами на УДАЛЕНИЕ, ВСТАВКУ и ОБНОВЛЕНИЕ.) В этом случае вам следует написать код, чтобы убедиться, что это число, и самый простой способ сделать это-intval()
Ответ №1:
Ну, переменные сеанса на самом деле являются одним из единственных способов (и, вероятно, наиболее эффективным) обеспечения доступности этих переменных в течение всего времени пребывания посетителя на веб-сайте, для пользователя нет реального способа их редактирования (кроме эксплойта в вашем коде или в интерпретаторе PHP), поэтому они достаточно безопасны.
Это хороший способ хранения настроек, которые могут быть изменены пользователем, так как вы можете прочитать настройки из базы данных один раз в начале сеанса, и они доступны для всего сеанса, вам нужно только выполнить дальнейшие вызовы базы данных, если настройки изменены, и, конечно, как вы показываете в своем коде, тривиально выяснить, существуют ли настройки уже или их нужно извлечь из базы данных.
Я не могу придумать никакого другого способа безопасного хранения временных переменных (поскольку файлы cookie могут быть легко изменены, и в большинстве случаев это будет нежелательно), поэтому $_SESSION будет правильным решением
Комментарии:
1. «они достаточно безопасны» верно только в том случае, если это выделенный сервер. на общем хостинге другие пользователи на той же машине могут получить доступ к данным php-сеанса.
2. Нет, если вы решите хранить данные о сеансе в каком-либо месте, отличном от места по умолчанию. Или когда вы используете другой механизм хранения сеансов, например базу данных или (ваш собственный личный) memcache.
Ответ №2:
Механизм $_SESSION использует файлы cookie.
В случае Firefox (и, возможно, нового IE, я сам не проверял) это означает, что сеанс разделяется между открытыми вкладками. Это не то, что вы ожидаете по умолчанию. И это означает, что сеанс больше не является «чем-то специфичным для одного окна/пользователя».
Например, если вы открыли две вкладки для доступа к сайту, а не вошли в систему как пользователь root с помощью первой вкладки, вы получите привилегии root на другой вкладке.
Это действительно неудобно, особенно если вы кодируете почтовый клиент или что-то другое (например, интернет-магазин). В этом случае вам придется управлять сеансами вручную или вводить постоянно обновляемый ключ в URL-адрес или делать что-то еще.
Ответ №3:
Я постоянно использую переменную сеанса для хранения информации для пользователей. Я не видел никаких проблем с производительностью. Данные сеанса извлекаются на основе файла cookie (или PHPSESSID, если у вас отключены файлы cookie). Я не вижу в этом большей угрозы безопасности, чем в любой другой аутентификации на основе файлов cookie, и, вероятно, более безопасной, чем хранение фактических данных в файлах cookie пользователей.
Просто чтобы вы знали, однако, у вас есть проблема с безопасностью в вашей инструкции SQL:
SELECT participationcode, modulearray, wavenum FROM mng_wave WHERE wave_id=".$_GET['wave_id'];
Вы НИКОГДА не должны, Я ПОВТОРЯЮ НИКОГДА, брать предоставленные пользователем данные и использовать их для выполнения инструкции SQL без предварительной очистки. Я бы заключил его в кавычки и добавил функцию mysql_real_escape_string()
. Это защитит вас от большинства атак. Таким образом, ваша линия будет выглядеть так:
$query_taskinfo = "SELECT participationcode, modulearray, wavenum FROM mng_wave WHERE wave_id='".mysql_real_escape_string($_GET['wave_id'])."'";
Ответ №4:
Есть несколько факторов, которые вы захотите учесть при принятии решения о том, где хранить временные данные. Хранилище сеансов отлично подходит для хранения данных, специфичных для одного пользователя. Если вы обнаружите, что обработчик хранения сеансов на основе файлов по умолчанию неэффективен, вы можете реализовать что-то другое, возможно, используя серверную часть типа базы данных или memcache. Дополнительную информацию смотрите в разделе session_set_save_handler.
Я считаю, что хранить общие данные в сеансе пользователя-плохая практика. Есть лучшие места для хранения данных, к которым часто будут обращаться несколько пользователей, и, сохраняя эти данные в сеансе, вы будете дублировать данные для каждого пользователя, которому нужны эти данные. В вашем примере вы можете настроить другой тип механизма хранения для этих волновых данных (на основе wave_id), который НЕ привязан конкретно к сеансу пользователя. Таким образом, вы один раз извлекете данные, и они сохранят их где-нибудь, чтобы несколько пользователей могли получить доступ к данным, не требуя повторного извлечения.
Ответ №5:
Если вы работаете на своем собственном сервере или в среде, где никто не может шпионить за вашими файлами/памятью на сервере, данные сеанса защищены. Они хранятся на сервере и просто отправляют клиенту идентификационный файл cookie. Проблема, конечно, в том, что другие люди могут выхватить печенье и выдать себя за кого-то другого. Использование HTTPS и отсутствие указания идентификатора сеанса в URL-адресах должно обезопасить ваших пользователей от большинства из этих проблем. (XSS все еще может использоваться для захвата файлов cookie, если вы не будете осторожны, см. Сообщение Jeef Atwoods об этом тоже.)
Что касается того, что хранить в переменной сеанса, поместите туда свои данные, если вы хотите снова обратиться к ним на другой странице, например, в корзине покупок, но не помещайте их туда, если это просто временные данные, используемые для получения результата этой страницы, например, список тегов для просматриваемого в данный момент сообщения. Сеансы предназначены для постоянных данных для каждого пользователя.
Ответ №6:
Другой способ улучшить проверку ввода-привести переменную _GET[‘wave_id’]:
$query_taskinfo = "SELECT participationcode, modulearray, wavenum FROM mng_wave WHERE wave_id=".(int)$_GET['wave_id']." LIMIT 1";
Я предполагаю, что wave_id-целое число, и что есть только один ответ.
Будет
Ответ №7:
Несколько других недостатков использования сеансов:
$_SESSION
срок действия данных истекает после нескольких секунд бездействия session.gc_maxlifetime.- Вам нужно будет не забывать вызывать
session_start()
каждый сценарий, который будет использовать данные сеанса. - Масштабирование веб-сайта путем балансировки нагрузки на нескольких серверах может стать проблемой, поскольку пользователя каждый раз нужно будет направлять на один и тот же сервер. Решите эту проблему с помощью «Липких сеансов».
Ответ №8:
Элементы $_SESSION хранятся в сеансе, который по умолчанию хранится на диске. Нет необходимости создавать свой собственный массив и помещать его в запись массива «dataentry», как вы это сделали. Вы можете просто использовать $_SESSION[‘pcode’], $_SESSION[‘модули’] и так далее.
Как я уже сказал, сеанс хранится на диске, а указатель на сеанс хранится в файле cookie. Таким образом, пользователь не может легко получить доступ к данным сеанса.
Комментарии:
1. Просто используйте многомерный массив $_SESSION[‘mystuff’][‘mydata’] = ‘бла’;
2. @conmulligan: Конечно, но на сессии не будет ничего, кроме того, что вы там разместили. Возможно, вы путаете $_SESSION с $_SERVER.
Ответ №9:
ИМО, вполне допустимо хранить вещи в сеансе. Это отличный способ сделать данные постоянными. Кроме того, во многих случаях это более безопасно, чем хранить все в файлах cookie. Вот несколько проблем:
- Кто-то может перехватить сеанс, поэтому, если вы собираетесь использовать его для отслеживания авторизации пользователя, будьте осторожны. Прочитайте это для получения дополнительной информации.
- Это может быть очень ленивый способ хранения данных. Не просто бросайте все в сеансе, чтобы вам не пришлось запрашивать это позже.
- Если вы собираетесь хранить объекты в сеансе, либо файлы их классов необходимо будет включить до начала сеанса при следующем запросе, либо вам потребуется настроить автоматический загрузчик.
Ответ №10:
Zend Framework имеет полезную библиотеку для управления данными сеанса, которая помогает с истечением срока действия и безопасностью (для таких вещей, как капчи). У них также есть полезное объяснение сеансов. Видишь http://framework.zend.com/manual/en/zend.session.html
Ответ №11:
Я обнаружил, что сеансы очень полезны, но следует отметить несколько вещей:
1) Что PHP может хранить ваши сеансы в папке tmp или другом каталоге, который может быть доступен другим пользователям на вашем сервере. Вы можете изменить каталог, в котором хранятся сеансы, перейдя в файл php.ini.
2) Если вы настраиваете систему высокой ценности, которая нуждается в очень строгой безопасности, вы можете зашифровать данные перед отправкой в сеанс и расшифровать их для использования. Примечание: это может привести к слишком большим затратам в зависимости от емкости вашего трафика / сервера.
3) Я обнаружил, что session_destroy(); не удаляет сеанс сразу, вам все равно придется ждать, пока сборщик мусора PHP очистит сеансы. Вы можете изменить частоту запуска сборщика мусора в файле php.ini. Но это все еще не кажется очень надежным, дополнительная информация http://www.captain.at/howto-php-sessions.php
Ответ №12:
Возможно, вы захотите подумать о том, насколько это УДОБНО?
т. е. смотрите параграф «Общение без участия государства» в разделе «Краткое введение в REST«…
«REST предписывает, чтобы это состояние было либо преобразовано в состояние ресурса, либо сохранено на клиенте. Другими словами, сервер не должен сохранять какое-либо состояние связи для любого из клиентов, с которыми он взаимодействует, помимо одного запроса».
(или любая другая ссылка в википедии для ОТДЫХА)
Итак, в вашем случае «wave_id» — это разумный ресурс для ПОЛУЧЕНИЯ, но действительно ли вы хотите сохранить его в СЕАНСЕ? Конечно, memcached-это ваше решение для кэширования ресурса объекта?
Ответ №13:
Я часто использую этот подход, я не вижу в этом никаких проблем. В отличие от файлов cookie, данные не хранятся на стороне клиента, что часто является большой ошибкой.
Как и все остальное, просто будьте осторожны, чтобы всегда очищать пользовательский ввод, особенно если вы вводите пользовательский ввод в переменную $_SESSION, а затем используете эту переменную в SQL-запросе.
Ответ №14:
Это довольно распространенная вещь, и сеанс, как правило, будет проходить быстрее, чем непрерывные обращения к базе данных. Они также достаточно безопасны, так как разработчики PHP усердно работали, чтобы предотвратить захват сеансов.
Единственная проблема заключается в том, что вам нужно не забывать перестраивать запись сеанса, когда что-то меняется. И, если что-либо изменится пользователем, отличным от того, кому принадлежит сеанс, что приведет к необходимости обновить этот ключ, нет простого способа уведомить систему об обновлении этого ключа сеанса. Возможно, это не имеет большого значения, но кое-что, о чем вы должны знать.
Ответ №15:
$_SESSION очень полезен с точки зрения безопасности, так как это серверный способ хранения информации, когда пользователь активно находится на ваших страницах, поэтому его трудно взломать, если только у вашего реального php-файла или сервера нет слабых мест, которые используются. Одной из очень хороших реализаций является сохранение переменной для подтверждения того, что пользователь вошел в систему, и разрешение на выполнение действий только в том случае, если они подтверждены.