Для моего веб-сайта управление сеансами в основном работает нормально. Сессии создаются, сохраняются и используются позже без проблем.
Но когда код использует session_start (), он всегда создает новый, полностью пустой сеанс. Кодекс, о котором идет речь ниже.
header('Content-Type: text/html; charset=UTF-8'); $main_domain = $_SERVER["HTTP_HOST"]; $expld = explode('.', $main_domain); if(count($expld) > 2) { $tld = array_pop($expld); $domain = array_pop($expld); $main_domain = $domain . "." . $tld; } session_set_cookie_params (0, '/', $main_domain); session_name('sid'); session_start(); echo session_id(); exit;
Когда этот скрипт выполняется, в каждой перезагрузке создается новый сеанс.
smar@ran ~> ls /tmp/sess_* | wc -l 10 smar@ran ~> ls /tmp/sess_* | wc -l 11 .. smar@ran ~> ls /tmp/sess_* | wc -l 17
Но только одна из этих сессий содержит в себе какие-либо данные и используется приложением.
Вывод в браузере всегда такой же: 87412d5882jr85gh5mkasmngg7
, который является идентификатором в cookie браузера и идентификатором сеанса в / tmp, который имеет данные, заполненные им.
Что может быть причиной такого поведения? Эти пустые файлы – это не совсем огромная проблема, но они делают make / tmp (или session dir) совершенно заполненным без каких-либо причин.
ИЗМЕНИТЬ 1:
Похоже, что это проблема, связанная с сервером, поскольку она работает для некоторых людей. Моя конфигурация – Gentoo Linux (32 бит) с Apache и PHP 5.3.6.
Если я заставляю его создавать новый сеанс (например, удалять свой собственный файл cookie), он создает два файла сеанса вместо одного. Если он повторяет старый, он создает только «один».
EDIT 2:
Конфигурация сеанса в соответствии с запросом (все строки конфигурации с session.
):
session.save_handler = files session.save_path = "/tmp" session.use_cookies = 1 session.use_only_cookies = 1 session.name = PHPSESSID session.auto_start = 0 session.cookie_lifetime = 0 session.cookie_path = / session.cookie_domain = session.cookie_httponly = session.serialize_handler = php session.gc_probability = 1 session.gc_divisor = 1000 session.gc_maxlifetime = 1440 session.bug_compat_42 = On session.bug_compat_warn = On session.referer_check = session.entropy_length = 0 session.entropy_file = session.cache_limiter = nocache session.cache_expire = 180 session.use_trans_sid = 0 session.hash_function = 0 session.hash_bits_per_character = 5
ИЗМЕНИТЬ 3:
Еще более странно, я пытался использовать сеансы из CLI. Там, где не настроены файлы cookie сеанса, он всегда создавал один новый сеанс. При установке фиксированного значения сеанса с session_id()
прекращается создание нового сеанса и вместо этого используется старый сеанс.
Такое поведение идентично Apache, поэтому я начинаю подозревать, что это ошибка в PHP. Никаких новых сеансов не создано, если имя специально задано с session_id()
и правильно используется сеанс.
Еще более абсурдно, когда я взял phpsessid из $_COOKIE["PHPSESSID"]
и установил его на session_id (), он снова начал создавать новые (бесполезные пустые) сеансы.
EDIT 4:
Поскольку я не писал достаточно ясно: просто имея
session_start()
поскольку один аргумент вызывает эту проблему, это не относится к моему коду.
Куки-файлы возвращаются только на vhost / path, из которых они были установлены.
Поскольку ваш путь равен '/', это означает, что страницы не запрашиваются через $ domain. "" , $ TLD;
например, страница запросов пользователей через http://www.example.com
cookie установлен для example.com
пользовательский доступ к следующей странице с сайта http://www.example.com – cookie не входит в объем.
Из RFC 2965
xycom domain-matches .Y.com, но не Y.com.
На самом деле, если вы читаете, спецификация говорит, что пользовательский агент должен префикс хоста точкой, если ни один не поставляется, но вы попадаете в область, где поведение браузера изменяется.
Если вы просто вернете файл cookie с помощью vhost, соответствующего запросу, он будет работать так, как ожидалось.
Используйте session_start()
как команду первого сеанса перед всеми другими методами session_*()
!
Это не совсем о первоначальной причине, но разрешение точно такое же: новые идентификаторы сеансов определяются с каждой перезагрузкой.
В этом случае ошибкой был Varnish, который был настроен на то, чтобы каждый запрос передавал режим ( return (pass)
) вместо кэширования всего. Как следствие, каждый запрос сделал это на бэкэнд, где session_start () вызывался каждый раз.
Но когда ответ был отправлен через Varnish клиенту, куки были удалены из ответа. Это связано с тем, что бэкэнд устанавливает файлы cookie (идентификатор сеанса вместе с другими), даже если мы хотим, чтобы сайт был кэширован. В любом случае, файлы cookie удаляются, клиент выполняет другой запрос и не передает никаких файлов cookie (он никогда не получал никаких!), И там PHP снова вызывается session_start () без присутствия идентификатора сеанса …
Это скорее ошибка в распознавании ошибки в этом случае, которая появилась как множество ненужных сеансов. Они не были бы созданы на первом месте, если бы на первом месте было включено кэширование.
Существует также другой способ управления этими сеансами: иметь браузер, чтобы не принимать файлы cookie вообще. Глупый разум, я знаю, но это происходит …
Для оригинальной проблемы я не наткнулся на нее, так как перешел с оригинальной машины разработки.
Я думаю, что powtac прав в некотором смысле, но session_start();
должна быть ваша первая операция, которую вы делаете, даже перед header('Content-Type: text/html; charset=UTF-8');
Я бы не хотел быть палкой в грязи, но вы проверили, что /tmp
читается и записывается PHP (в большинстве случаев это означает, что пользователь www-data)? Если нет, переместите место сохранения сеанса в место, в которое вы можете записать.