#Симптомы, область применения и причины
После успешного session_start() приложение снова просит войти или не видит значение $_SESSION. По шагам проверяем идентификатор cookie, домен, HTTPS, разные серверы и хранилище сеансов. Здесь речь не об ошибке Permission denied при записи сеанса, а о ситуации, когда вызов session_start() проходит, но следующий HTTP-запрос получает новый сеанс или не читает данные из прежнего.
| Возможная причина | Как узнать | Что делать |
|---|---|---|
| Браузер не возвращает cookie идентификатораCookie ограничен другим доменом, путём, Secure или SameSite. | В ответе есть Set-Cookie, а в следующем запросе отсутствует Cookie с идентификатором сеанса. | Сопоставить параметры cookie с фактическим HTTPS-адресом сайта. |
| Разные серверы используют разные хранилищаБалансировщик направляет запросы в разные PHP-FPM-узлы с локальным session.save_path. | При обновлении значение $_SESSION появляется через раз; зависит от backend-узла. | Использовать общее корректно настроенное серверное хранилище либо закрепить маршрутизацию временно для диагностики. |
| Сеанс уничтожается или сохраняется не тудаКод вызывает session_regenerate_id, session_destroy либо использует короткий gc_maxlifetime или разный session.save_handler. | Cookie приходит стабильно, но данные пропадают сразу или через короткое время. | Проверить путь выполнения, таймауты и место хранения без удаления всех сеансов. |
#Безопасная диагностика и пошаговое исправление
- Подтвердите, что пропадает именно сеансОткройте сайт в отдельном профиле браузера и выполните одно простое действие, которое записывает значение в сессию (например, вход в тестовую учётную запись). Обновите страницу один раз; запишите время, адрес, случился ли выход и присутствует ли перенаправление с HTTP на HTTPS или между доменами. Если исчезает только оформление, а авторизация остаётся, проблема может быть в другом хранилище, а не в session_start().
- Посмотрите cookie на двух последовательных запросахВ Chrome/Firefox нажмите F12 → «Сеть», включите сохранение журнала, обновите страницу и выберите первый запрос. В «Заголовках» посмотрите
Set-Cookie; затем выберите следующий запрос того же домена и найдите заголовокCookie. Имя PHP-сеанса по умолчанию PHPSESSID, но приложение может установить иное. Не копируйте значение cookie, оно может предоставлять доступ к аккаунту. Если cookie не возвращается, проверьтеDomain,Path,Secureи срок действия.
- Проверьте HTTPS, домен и путиСравните реальный адрес сайта с параметрами
session.cookie_domain,session.cookie_path,session.cookie_secure,session.cookie_samesite. Для HTTPS cookie с Secure корректна, но на HTTP браузер её не отправит. Если приложение переносит пользователя сwww.example.testна другой поддомен, cookie без подходящего Domain не перейдёт туда. Не отключайте Secure для рабочего сайта: исправьте схему HTTPS или согласуйте домен с архитектором. Убедитесь, что приложение не перенаправляет пользователя между разными хостами.
- Снимите безопасные диагностические показатели в веб-запросеРазработчик может на время записать в закрытый журнал значения
session_status(),session_name(),ini_get("session.save_handler")иini_get("session.save_path"). Самsession_id()и данные сеанса нельзя записывать целиком в доступный журнал; для сопоставления запросов используйте безопасный случайный идентификатор тестового действия, не связанный с действительным сеансовым cookie. Проверьте, чтоsession_start()вызывается до вывода HTML. - Пример кода по темеPHPТестовые сообщения не содержат cookie и пользовательских данных; удалите диагностический код после проверки.
<?php // Только закрытая тестовая страница; не выводите ID сеанса. $ok = session_start(); error_log('session started: '.($ok ? 'yes' : 'no')); error_log('handler: '.ini_get('session.save_handler')); error_log('storage configured: '.(ini_get('session.save_path') !== '' ? 'yes' : 'default'));
- Проверьте фактическое хранилище и срок жизниВ панели параметров PHP домена найдите
session.save_handler,session.save_path,session.gc_maxlifetime; у Redis/Memcached параметры задаются иначе и требуют соответствующего клиентского расширения. Если используетсяfiles, владелец процесса PHP-FPM должен иметь право записи в каталог. Но не выдавайте всему каталогу права 777. При проверке диска смотрите свободное место, права и ошибки журналов. Не удаляйте содержимое каталога сеансов: это немедленно разлогинит пользователей.
- Сравните соседние серверы и обработчики PHPЕсли перед сайтом есть балансировщик, попросите администратора посмотреть, на какой backend пришли два запроса. Проверьте, что у серверов одинаковые
session.save_handlerи логика приложений, а хранилище общее или предусмотрена устойчивость сеансов к распределению нагрузки. Если на одном сервере используется Redis, а на другом локальные файлы, данные будут исчезать. Не переключайте маршрутизацию рабочего кластера без плана отката.
- Найдите в коде явное уничтожение или смену идентификатораВ редакторе проекта выполните поиск по
session_destroy,session_unset,session_regenerate_idи по местам, где присваивается$_SESSION = []. Смена идентификатора после входа сама по себе правильна для безопасности, поэтому не удаляйтеsession_regenerate_idтолько ради теста; проверьте правильность переноса состояния и времени вызова. Если данные теряются через заданное время, сопоставьте его с политикой истечения приложения и сервера.
- Проверьте два запроса и сохраните возможность возвратаПосле точечного исправления cookie, пути или общего хранилища войдите в тестовый аккаунт, перейдите на вторую страницу и обновите её несколько раз, а затем проверьте работу после обычного срока паузы. Если тест не прошёл, верните прежние параметры PHP/балансировщика из копии; приложите к заявке только времена запросов и описания заголовков, без значения идентификатора сессии.
#Как проверить результат и что делать дальше
Успех — после двух последовательных запросов и обычной паузы авторизация и контрольное значение $_SESSION сохраняются, а браузер отправляет согласованный cookie. Если значение исчезает только на части узлов, нужна проверка общего хранилища и маршрутизации администратором.