Чего не работают сессии php

Чего не работают сессии php

БлогNot. PHP: 12 причин, по которым не работают сессии

PHP: 12 причин, по которым не работают сессии

Хотя PHP последних версий стал работать с сессиями гораздо лучше, начинающие (а порой и опытные) программисты всё ещё нередко мучаются с ними, особенно если речь идёт об адаптации старого кода к новым версиям. В этой заметке я собрал самые распространённые причины, по которым могут не работать сессии (авторизация не выполняется, вход на сайт происходит только со второго раза и т.п.)

Сначала разумные причины:

1. Сессия не запущена.

То есть, не вызывалась функция session_start. Самая банальная и самая частая причина. Вызов session_start должен выполняться на каждой странице, где используются данные из массива $_SESSION .

Лучше всего вызывать session_start сразу после открывающего тега

Я часто в запутанном коде из множества модулей делаю это в виде

Есть смысл также запускать сессию только из модуля с функциями, подключаемыми к каждой странице сайта кодом вроде этого:

2. Сессия или её данные удаляются из кода раньше, чем должны использоваться.

В сложных многомодульных скриптах это вполне возможно, тем более, сделать это можно несколькими способами — через функцию session_destroy, «прямой» очисткой массива сессии кодом вида $_SESSION = array(); или $_SESSION = []; или unset($_SESSION[‘name’]) или просто unset($_SESSION); — в последнем случае, правда, сгенерируется предупреждение. «Прошерстите» код, чтобы убедиться, что этого не происходит.

3. Хранилище сессии недоступно для записи.

Выполните на хосте функцию phpinfo и проверьте значение session.save_path — это папка, куда сохраняется сессия.

Зайдите в неё и посмотрите, есть ли там свежие файлы с именами вроде sess_***** или *****.tmp . Если файлов нет — сессия не может сохраниться из-за отстутствия прав на доступ к папке. Установите их.

4. Данные сессии не записываются после отправки заголовка.

Если страница после выполнения кода редиректит на другую страницу при помощи функции header, может понадобиться добавить непосредственно после вызова header вызов функции session_write_close (или exit , die ), чтобы сессия могла корректно записать данные.

5. В браузере не включены Cookies.

Механизм куки-файлов необходим для работы сессий. Проверьте, что куки разрешены в браузере.

6. В коде или настройках сайта происходит редирект с одного домена на другой.

При редиректе сессия потеряется, даже если это редирект с site.com на www.site.com или наоборот.

7. Некорректная работа со временем в скрипте.

Скрипт имеет тысячу и один способ использовать время, отличающееся от серверного, в том числе, ставить время для куки и т.п.

А что если в момент создания кука оказывается уже просроченной?

Неплохо также в файле .htaccess настроить часовой пояс явно, скажем

8. Устаревшие функции сессий.

Например, код всё ещё использует session_register, а она давно удалена из языка. Проверьте и другие функции сессий — нужно ли их все применять?

Мне сегодня помог п. 4 при «реанимации» работающего «со второго входа» сайтега.

Теперь причины более экзотические, которых, вроде бы, не должно быть, а они случаются.

9. На сайте нет файла favicon.ico или favicon.png

Некоторым бразуерам (Chrome) на некоторых серверах (nginx) это может помешать работе с сессиями, хотя понятных причин я назвать не могу.

10. У вас в файле кодировка UTF-8 с меткой BOM.

Избавьтесь от неё. Хотя, по идее, вы должны были увидеть раньше популярнейшее предупреждение (warning) «headers already sent» (см. по ссылке). Но бывает, что не усмотрел директивы отключения варнингов где-нибудь в недрах кода. Кстати, включите контроль всех ошибок при работе.

11. Лишние символы, например, пробелы после закрывающего тега PHP ?>

Что тут сказать? Избавьтесь от них.

12. Так легла карта.

Скорее всего, сессия просто стартует не там, где Вы думаете.

Источник

Семь причин почему не сохраняется сессия в PHP

Когда вебмастер начинает работать с сессиями, он часто сталкивается с тем, что сессия не сохраняется при переходе на другую страницу. Причин может быть множество, ниже представлен список наиболее распространённых, изучив которые, вы сможете решить проблему.

Почему не сохраняется сессия при переходе на другую страницу?

1. Вы забыли запустить сессию

Пожалуй, это самая распространённая причина почему не сохраняется сессия. Запуск сессии посредством функции session_start(); должен осуществляться на каждой странице, где используется сессия. Лучше всего session_start(); писать сразу после открывающего тега

2. Сессия уничтожается в коде

Прежде чем пропускать этот пункт и идти далее с мыслью «Да ну, бред какой-то, нигде я сессию не уничтожаю.», удостоверьтесь, действительно ли вы нигде не очищаете сессию? Уничтожить сессию можно с помощью функции session_destroy(); или вы можете очистить значения сессии путём следующей конструкции: unset($_SESSION[‘name’]); . Убедитесь, что у вас этого нет.

3. Хранилище сессии недоступно для записи

Для начала проверьте куда у вас записывается сессия. Выполните phpinfo(); и посмотрите значение параметра session.save_path . Это и есть директория, куда сохраняется сессия. Зайдите в неё и посмотрите, есть ли там файлы типа «0Thee5g9vsknDhen14kyYt5lv7» . Если файлов нет, значит сессия не может сохраниться, посмотрите правильно ли выставлены права доступа к директории.

4. После отправки заголовка не используется exit();

В случае, если на странице отправляются заголовки при помощи функции header() , необходимо добавить конструкцию exit(); или session_write_close(); , чтобы сессия могла корректно отработать.

5. Cookies не включены в браузере

Убедитесь, что использование cookies разрешено в браузере, в котором используется сайт.

Читайте также:  Как настроить мышь майкрософт блютуз

6. Редирект с одного домена на другой

При редиректе с одного домена на другой сессия потеряется. Даже если это один домен и он отличается наличием «www», например при перенаправлении с «site.com» на «www.site.com» сессия пропадёт, убедитесь, что у вас этого не происходит.

7. У вас нет favicon.ico

Пожалуй, самая экзотическая из всех вышеперечисленных причин, почему сессия может не сохранятся. Я не знаю почему так происходит, но если у вас нет favicon’а на сайте, браузер Google Chrome может «потерять» вашу сессию. Это бывает не на всех серверах, подобный глюк я обнаружил на nginx’е.

Здравствуй дорогой читатель! Я рад приветствовать тебя на страницах моего блога. Уже несколько лет я занимаюсь веб-программированием и рад поделиться с тобой своими знаниями и советами. Если тебе понравились мои статьи, ты можешь подписаться на рассылку блога, из неё ты узнаешь много интересного!

полдня сегодня мучился над http://www.bestflora.ru/, оказывается UTF был с сигнатурой сохранен! :)) Так что тоже берите на заметку

Есть ещё одна. Если произошел вывод текста(пробельные символы после закрывающего тэга PHP), до session_start(). сессия также может слететь. Но не всегда. Кто-нибудь может объяснить, почему так происходит

Источник

Не работают сесии на сайте

Доброго времени господа знатоки) такая проблема поставила меня в тупик — делал я много сайтов на всех использовал один и тот же скрипт запуска и записи данных в сессии а именно

так запускаю — документ сохранен в ютф- без бом(!) — все как полагается сессия запускается в сааааамом начале документа — перед функцией запуска нету ни одного символа тут все по фэншую

записываю в сессию вот так

проверяю допустим так

и не работает( при том — на локальном хосте — все работает идеально — на 20ти других сайтов работает тоже один и тот же этот скрипт!

замечу что этот сайт на котором не работает сей простой скрипт — находится на совершенно другом хостинге чем те 10 сайтов на которых все работает (не говорю уже об ЛХ) хостинг панель rshost (если это поможет) предоставлен видимо ISPsystem © 1997-2015 (в копирайте написано) я в начале думал что просто в тупую на хосте отключены сессии НО до этого на хосте стоял старый сайт на джумле и там все было настроено через сессии и все вроде как работало, я в тупике господа подскажите пожалуйста — вдруг кто то с похожим сталкивался?

Забыл возможно это важно! после того как юзер авторизуется и через пост передаются логин пароль в обработчик (который на этой же странице что и форма) для проверки — после того если проверка прошла и данные заносятся в сессию — страница обновляется через js так

что бы очистить переменные POST

2 ответа 2

При подобных проблемах следует выяснить следующее:

  1. Включен-ли механизм передачи идентификаторов сессий на хостинге? Вывести значение session_id() (если PHP собран без поддержки сессий будет выдана ошибка об отсутствии функции) или связаться с провайдером;
  2. Вызывается-ли функция session_start() ? Иногда бывает так, что старт сессии происходит в поключаемом при каком-либо условии файле или функции. Чтобы удостовериться можно создать перед сессией искуственную критическую ошибку или вывод контрольной строки в error_log;
  3. Появляются-ли в error_log новые ошибки? При их появлении следует устранить причины их появления;
  4. Меняется-ли каждом входе на страницу значение функции session_id() в рамках одной сессии? Если не меняется, то скорее всего данные сессии не сохраняются и в п. 2 будет соответствующая ошибка (невозможность записи в файл или если применяются другие механизмы хранения сессии могут быть проблемы записи в базу). Если меняется, то нужно переходить к следующему пункту;
  5. Передаются-ли куки от сервера к клиенту и обратно? Нужно смотреть на HTTP-заголовки запроса Cookie и заголовки ответа Set-Cookie при помощи средств разработки браузера или при помощи сниффера (например Wireshark или tcpdump). Если они не передаются от браузера говорит о запрете их хранения в браузере. Если куки не передаются к браузеру говорит о том, что заголовки не передаются из-за того, что PHP-скрипт уже начал формировать контент страницы до начала сессии. Одна из причин, приводящих к этой проблеме — наличие маркера последовательности байтов в начале PHP-скрипта.

Источник

PHP для начинающих. Сессия

Всем хорошего дня. Перед вами первая статья из серии PHP для начинающих разработчиков. Это будет необычная серия статей, тут не будет echo «Hello World» , тут будет hardcore из жизни PHP программистов с небольшой примесью «домашней работы» для закрепления материала.

Начну с сессий — это один из самых важных компонентов, с которыми вам придется работать. Не понимая принципов его работы — наворотите делов. Так что во избежание проблем я постараюсь рассказать о всех возможных нюансах.

Но для начала, чтобы понять зачем нам сессия, обратимся к истокам — к HTTP протоколу.

HTTP Protocol

Изначально подразумевали, что по этому протоколу будет только HTML передаваться, отсель и название, а сейчас чего только не отправляют и =^.^= и(•_ㅅ_•)

Чтобы не ходить вокруг да около, давайте я вам приведу пример общения по HTTP протоколу.
Вот пример запроса, каким его отправляет ваш браузер, когда вы запрашиваете страницу http://example.com :

А вот пример ответа:

Это очень упрощенные примеры, но и тут можно увидеть из чего состоят HTTP запрос и ответ:

  1. стартовая строка — для запроса содержит метод и путь запрашиваемой страницы, для ответа — версию протокола и код ответа
  2. заголовки — имеют формат ключ-значение разделенные двоеточием, каждый новый заголовок пишется с новой строки
  3. тело сообщения — непосредственно HTML либо данные отделяют от заголовков двумя переносами строки, могут отсутствовать, как в приведенном запросе

Так, вроде с протоколом разобрались — он простой, ведёт свою историю аж с 1992-го года, так что идеальным его не назовешь, но какой есть — отправили запрос — получите ответ, и всё, сервер и клиент никоим образом более не связаны. Но подобный сценарий отнюдь не единственный возможный, у нас же может быть авторизация, сервер должен каким-то образом понимать, что вот этот запрос пришёл от определенного пользователя, т.е. клиент и сервер должны общаться в рамках некой сессии. И да, для этого придумали следующий механизм:

  1. При авторизации пользователя, сервер генерирует и запоминает уникальный ключ — идентификатор сессии, и сообщает его браузеру
  2. Браузер сохраняет этот ключ, и при каждом последующем запросе, его отправляет
Читайте также:  Уфанет не работает кабельное телевидение сегодня

Для реализации этого механизма и были созданы cookie (куки, печеньки) — простые текстовые файлы на вашем компьютере, по файлу для каждого домена (хотя некоторые браузеры более продвинутые, и используют для хранения SQLite базу данных), при этом браузер накладывает ограничение на количество записей и размер хранимых данных (для большинства браузеров это 4096 байт, см. RFC 2109 от 1997-го года)

Т.е. если украсть cookie из вашего браузера, то можно будет зайти на вашу страничку в facebook от вашего имени? Не пугайтесь, так сделать нельзя, по крайней мере с facebook, и дальше я вам покажу один из возможных способов защиты от данного вида атаки на ваших пользователей.

Давайте теперь посмотрим как изменятся наши запрос-ответ, будь там авторизация:

Метод у нас изменился на POST, и в теле запроса у нас передаются логин и пароль. Если использовать метод GET, то строка запроса будет содержать логин и пароль, что не очень правильно с идеологической точки зрения, и имеет ряд побочных явлений в виде логирования (например, в том же access.log ) и кеширования паролей в открытом виде.

Ответ сервер будет содержать заголовок Set-Cookie: KEY=VerySecretUniqueKey , что заставит браузер сохранить эти данные в файлы cookie, и при следующем обращении к серверу — они будут отправлены и опознаны сервером:

Как можно заметить, заголовки отправляемые браузером (Request Headers) и сервером (Response Headers) отличаются, хотя есть и общие и для запросов и для ответов (General Headers)

Сервер узнал нашего пользователя по присланным cookie, и дальше предоставит ему доступ к личной информации. Так, ну вроде с сессиями и HTTP разобрались, теперь можно вернутся к PHP и его особенностям.

PHP и сессия

Я надеюсь, у вас уже установлен PHP на компьютере, т.к. дальше я буду приводить примеры, и их надо будет запускать

Вот вам статейка на тему PHP is meant to die, или вот она же на русском языке, но лучше отложите её в закладки «на потом».

Перво-наперво необходимо «стартовать» сессию — для этого воспользуемся функцией session_start(), создайте файл session.start.php со следующим содержимым:

Запустите встроенный в PHP web-server в папке с вашим скриптом:

Запустите браузер, и откройте в нём Developer Tools (или что там у вас), далее перейдите на страницу http://127.0.0.1:8080/session.start.php — вы должны увидеть лишь пустую страницу, но не спешите закрывать — посмотрите на заголовки которые нам прислал сервер:

Там будет много чего, интересует нас только вот эта строчка в ответе сервера (почистите куки, если нет такой строчки, и обновите страницу):

Увидев сие, браузер сохранит у себя куку с именем `PHPSESSID`:

PHPSESSID — имя сессии по умолчанию, регулируется из конфига php.ini директивой session.name, при необходимости имя можно изменить в самом конфигурационном файле или с помощью функции session_name()

И теперь — обновляем страничку, и видим, что браузер отправляет эту куку на сервер, можете попробовать пару раз обновить страницу, результат будет идентичным:

Итого, что мы имеем — теория совпала с практикой, и это просто отлично.

Следующий шаг — сохраним в сессию произвольное значение, для этого в PHP используется супер-глобальная переменная $_SESSION , сохранять будем текущее время — для этого вызовем функцию date():

Обновляем страничку и видим время сервера, обновляем ещё раз — и время обновилось. Давайте теперь сделаем так, чтобы установленное время не изменялось при каждом обновлении страницы:

Обновляем — время не меняется, то что нужно. Но при этом мы помним, PHP умирает, значит данную сессию он где-то хранит, и мы найдём это место…

Всё тайное становится явным

В вашей конфигурации путь к файлам может быть не указан, тогда файлы сессии будут хранится во временных файлах вашей системы — вызовите функцию sys_get_temp_dir() и узнайте где это потаённое место.

Так, идём по данному пути и находим ваш файл сессии (у меня это файл sess_dap83arr6r3b56e0q7t5i0qf91 ), откроем его в текстовом редакторе:

Как видим — вот оно наше время, вот в каком хитром формате хранится наша сессия, но мы можем внести правки, поменять время, или можем просто вписать любую строку, почему бы и нет:

Для преобразования этой строки в массив нужно воспользоваться функцией session_decode(), для обратного преобразования — session_encode() — это зовется сериализацией, вот только в PHP для сессий — она своя — особенная, хотя можно использовать и стандартную PHP сериализацию — пропишите в конфигурационной директиве session.serialize_handler значение php_serialize и будет вам счастье, и $_SESSION можно будет использовать без ограничений — в качестве индекса теперь вы сможете использовать цифры и специальные символы | и ! в имени (за все 10+ лет работы, ни разу не надо было 🙂

Напишите свою функцию, аналогичную по функционалу session_decode() , вот вам тестовый набор данных для сессии (для решения знаний регулярных выражений не требуется), текст для преобразования возьмите из файла вашей текущей сессии:

Так, что мы ещё не пробовали? Правильно — украсть «печеньки», давайте запустим другой браузер и добавим в него теже самые cookie. Я вам для этого простенький javascript написал, скопируйте его в консоль браузера и запустите, только не забудьте идентификатор сессии поменять на свой:

Вот теперь у вас оба браузера смотрят на одну и туже сессию. Я выше упоминал, что расскажу о способах защиты, рассмотрим самый простой способ — привяжем сессию к браузеру, точнее к тому, как браузер представляется серверу — будем запоминать User-Agent и проверять его каждый раз:

Это подделать сложнее, но всё ещё возможно, добавьте сюда ещё сохранение и проверку $_SERVER[‘REMOTE_ADDR’] и $_SERVER[‘HTTP_X_FORWARDED_FOR’] , и это уже более-менее будет похоже на защиту от злоумышленников посягающих на наши «печеньки».

Ключевое слово в предыдущем абзаце похоже, в реальных проектах cookies уже давно «бегают» по HTTPS протоколу, таким образом никто их не сможет украсть без физического доступа к вашему компьютеру или смартфону

Стоит упомянуть директиву session.cookie-httponly, благодаря ей сессионная кука будет недоступна из JavaScript’a. Кроме этого — если заглянуть в мануал функции setcookie(), то можно заметить, что последний параметр так же отвечает за HttpOnly. Помните об этом — эта настройка позволяет достаточно эффективно бороться с XSS атаками в практически всех браузерах.

Читайте также:  Как настроить гренни без гренни

По шагам

А теперь поясню по шагам алгоритм, как работает сессия в PHP, на примере следующего кода (настройки по умолчанию):

  1. после вызова session_start() PHP ищет в cookie идентификатор сессии по имени прописанном в session.name — это PHPSESSID
  2. если нет идентификатора — то он создаётся (см. session_id()), и создаёт пустой файл сессии по пути session.save_path с именем sess_ , в ответ сервера будет добавлены заголовки, для установки cookie =
  3. если идентификатор присутствует, то ищем файл сессии в папке session.save_path :
    • не находим — создаём пустой файл с именем sess_ <$_COOKIE[session_name()]>(идентификатор может содержать лишь символы из диапазонов a-z , A-Z , 0-9 , запятую и знак минус)
    • находим, читаем файл и распаковываем данные (см. session_decode()) в супер-глобальную переменную $_SESSION (файл блокируется для чтения/записи)
  4. когда скрипт закончил свою работу, то все данные из $_SESSION запаковывают с использованием session_encode() в файл по пути session.save_path с именем sess_ (блокировка снимается)

А есть ли жизнь без «печенек»?

PHP может работать с сессией даже если cookie в браузере отключены, но тогда все URL на сайте будут содержать параметр с идентификатором вашей сессии, и да — это ещё настроить надо, но оно вам надо? Мне не приходилось это использовать, но если очень хочется — я просто скажу где копать:

А если надо сессию в базе данных хранить?

Отдельно замечу, что не надо писать собственные обработчики сессий для redis и memcache — когда вы устанавливаете данные расширения, то вместе с ними идут и соответствующие обработчики, так что RTFM наше всё. Ну и да, обработчик нужно указывать до вызова session_start() 😉

Когда умирает сессия?

За время жизни сессии отвечает директива session.gc_maxlifetime. По умолчанию, данная директива равна 1440 секундам (24 минуты), понимать её следует так, что если к сессии не было обращении в течении заданного времени, то сессия будет считаться «протухшей» и будет ждать своей очереди на удаление.

Интересен другой вопрос, можете задать его матёрым разработчикам — когда PHP удаляет файлы просроченных сессий? Ответ есть в официальном руководстве, но не в явном виде — так что запоминайте:

Сборщик мусора (garbage collection) может запускаться при вызове функции session_start() , вероятность запуска зависит от двух директив session.gc_probability и session.gc_divisor, первая выступает в качестве делимого, вторая — делителя, и по умолчанию эти значения 1 и 100, т.е. вероятность того, что сборщик будет запущен и файлы сессий будут удалены — примерно 1%.

Самая тривиальная ошибка

Ошибка у которой более полумиллиона результатов в выдаче Google:

Cannot send session cookie — headers already sent by
Cannot send session cache limiter — headers already sent

Для получения таковой, создайте файл session.error.php со следующим содержимым:

Во второй строке странная «магия» — это фокус с буфером вывода, я ещё расскажу о нём в одной из следующих статей, пока считайте это лишь строкой длинной в 4096 символов, в данном случае — это всё пробелы

Запустите, предварительно удалив cookie, и получите приведенные ошибки, хоть текст ошибок и разный, но суть одна — поезд ушёл — сервер уже отправил браузеру содержимое страницы, и отправлять заголовки уже поздно, это не сработает, и в куках не появилось заветного идентификатора сессии. Если вы стокнулись с данной ошибкой — ищите место, где выводится текст раньше времени, это может быть пробел до символов , или после ?> в одном из подключаемых файлов, и ладно если это пробел, может быть и какой-нить непечатный символ вроде BOM, так что будьте внимательны, и вас сия зараза не коснется (как-же,… гомерический смех).

Для проверки полученных знаний, я хочу, чтобы вы реализовали свой собственный механизм сессий и заставили приведенный код работать:

Блокировка

Ещё одна распространённая ошибка у новичков — это попытка прочитать файл сессии пока он заблокирован другим скриптом. Собственно, это не совсем ошибка, это недопонимание принципа блокировки 🙂

Но давайте ещё раз по шагам:

  1. session_start() не только создаёт/читает файл, но и блокирует его, чтобы никто не мог внести правки в момент выполнения скрипта, или прочитать не консистентные данные из файла сессии
  2. блокировка снимается по окончанию выполнения скрипта

«Воткнутся» в данную ошибку очень легко, создайте два файла:

Теперь, если вы откроете в браузере страничку lock.php , а затем в новой вкладке откроете start.php то увидите, что вторая страничка откроется только после того, как отработает первый скрипт, который блокирует файл сессии на 10 секунд.

Есть пару вариантов, как избежать подобного явления — «топорный» и «продуманный».

«Топорный»
Использовать самописный обработчик сессий, в котором «забыть» реализовать блокировку 🙂
Чуть лучше вариант, это взять готовый и отключить блокировку (например у memcached есть такая опция — memcached.sess_locking) O_o
Потратить часы на дебаг кода в поисках редко всплывающей ошибки…

«Продуманный»
Куда как лучше — самому следить за блокировкой сессии, и снимать её, когда она не требуется:

— Если вы уверенны, что вам не потребуется вносить изменения в сессионные данные используйте опцию read_and_close при старте сессии:

Таким образом, блокировка будет снята сразу по прочтению данных сессии.

— Если вам таки нужно вносить изменения в сессию, то после внесения оных закрывайте сессию от записи:

В заключение

В этой статье вам дано семь заданий, при этом они касаются не только работы с сессиями, но так же познакомят вас с MySQL и с функциями работы со строками. Для усвоения этого материала — отдельной статьи не нужно, хватит и мануала по приведенным ссылкам — никто за вас его читать не будет. Дерзайте!

Источник

Оцените статью