Сессия PHP потеряна после перенаправления


132

Как решить проблему потери сеанса после перенаправления в PHP?

Недавно я столкнулся с очень частой проблемой потери сеанса после перенаправления. И после поиска на этом веб-сайте я все еще не могу найти решения (хотя это было самым близким).

Обновить

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


1
Вопрос в том, как решить проблему потери сеанса после редиректа в PHP. Я уже понял ответ, просто разместил его здесь, чтобы сообщить другим людям. Потому что моего решения нет на StackOverflow.
dayuloli

2
Это нормально, но это сайт QA. Пожалуйста, сделайте свой вопрос вопросом.
Джереми

Я не заметил, что это от тебя. Тем не менее, этот сайт предназначен для вопросов, а не для ответов на уже известные вам вопросы.
Aris


21
@Aris: Это неправда, когда у людей возникает вопрос о кодировании, они обращаются за помощью в StackOverflow. Если ответов нет, они не могут получить необходимую помощь. Я пытаюсь дать такой ответ.
dayuloli

Ответы:


209

Сначала выполните эти обычные проверки:

  1. Убедитесь, что session_start();вызывается перед вызовом любых сеансов. Таким образом, беспроигрышный вариант - разместить его в начале вашей страницы сразу после открывающего <?phpобъявления, прежде чем что-либо еще. Также убедитесь, что перед открывающим <?phpобъявлением нет пробелов / табуляции .
  2. После headerперенаправления завершите текущий сценарий, используя exit();(другие также предлагали, session_write_close();и session_regenerate_id(true)вы также можете попробовать их, но я бы использовал exit();)
  3. Убедитесь, что файлы cookie включены в браузере, который вы используете для тестирования.
  4. Убедитесь, register_globalsчто выключено, вы можете проверить это в php.iniфайле, а также с помощью phpinfo(). Обратитесь к этому, чтобы узнать, как его выключить.
  5. Убедитесь, что вы не удалили и не опустошили сеанс
  6. Убедитесь, что ключ в вашем $_SESSIONсуперглобальном массиве нигде не перезаписан
  7. Убедитесь, что вы перенаправляете на тот же домен. Таким образом, перенаправление с a www.yourdomain.comна yourdomain.comне переносит сеанс вперед.
  8. Убедитесь, что расширение вашего файла .php(такое бывает!)

Это наиболее распространенные ошибки, но если они не помогли, проблема, скорее всего, связана с вашей хостинговой компанией. Если все работает, localhostно не на вашем удаленном / тестовом сервере, то, скорее всего, виноват в этом. Так что проверьте базу знаний вашего хостинг-провайдера (также попробуйте их форумы и т. Д.). Для таких компаний, как FatCow и iPage, они требуют, чтобы вы указали session_save_path. Ну вот так:

session_save_path('"your home directory path"/cgi-bin/tmp');
session_start();

(замените «путь к вашему домашнему каталогу» фактическим путем к домашнему каталогу. Обычно он находится в панели управления (или аналогичной), но вы также можете создать test.phpфайл в корневом каталоге и ввести:

<?php echo $_SERVER['SCRIPT_FILENAME']; ?>

Бит перед test.php - это путь к вашему домашнему каталогу. И, конечно же, убедитесь, что папка действительно существует в вашем корневом каталоге. (Некоторые программы не выгружают пустые папки при синхронизации)


8
Очень хорошо написано +1, если все не удается, просто используйте файлы cookie (случайным образом сгенерируйте строку и сохраните ее в базе данных и используйте ее в качестве значения cookie).
Дэйв Чен

2
переключение между http иn https также может быть проблемой stackoverflow.com/questions/441496/…
dev.e.loper

4
Обратите внимание, что с php 5.4.0 register_globals был удален, поэтому он больше не будет вызывать проблем
Anthonygore

2
Также проверьте журнал ошибок веб-сервера; в моем случае произошла ошибка «Не удалось записать данные сеанса (файлы). Убедитесь, что текущая настройка session.save_path верна». Неправильные разрешения для каталога save_path.
timbonicus

Любая причина, по которой мои сеансы будут храниться где-нибудь, кроме session.save_path?
Джастин

26

вы должны использовать "exit" после вызова заголовка

header('Location: http://www.example.com/?blabla=blubb');
exit;

Существует ошибка для Gecko (например, Waterfox, Firefox, SeaMonkey), при которой, если есть какие-либо выходные данные (например echo ' ';) или какие-либо пробелы, он полностью игнорирует заголовок местоположения.
Джон

18

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

В конце концов, я решил проблему, используя «относительный URL» внутри заголовка перенаправления!

header("location: http://example.com/index.php")

аннулировал файлы cookie сеанса

header("location: index.php")

работал как шарм!


7

У меня такая же проблема. Я работал над этим несколько часов, и это сводило меня с ума.

В моем случае проблема заключалась в вызове 404 из- за отсутствия файла favicon.ico только в Chrome и Firefox. Остальные навигаторы работали нормально.


Просто хотел поблагодарить вас за этот ответ, заставивший меня понять, что 404 запроса на изображения перенаправлялись Varnish на PHP без каких-либо файлов cookie, и поэтому постоянно создавались новые сеансы. Возможно, никогда бы не понял этого без тебя.
Pascal Zajac

У меня была такая же проблема, мой favicon.ico перенаправлялся (302 перенаправление с поддомена на основной домен) и, таким образом, каждый раз создавал новый сеанс. Большое спасибо!
simdrouin

4

Когда я использую относительный путь "dir / file.php" с функцией header (), у меня работает. Я думаю, что сеанс почему-то не сохраняется при перенаправлении с использованием полного url ...

//Does retain the session info for some reason
header("Location: dir");

//Does not retain the session for some reason
header("Location: https://mywebz.com/dir")

3

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

session.use_cookies = 1 

Я думал, что сеансы работают без файлов cookie ... на самом деле я знаю, что они ДОЛЖНЫ ... но это решило мою проблему, по крайней мере, до тех пор, пока я не смогу понять, что может происходить в более широкой картине.


Я не знал, что сеансы могут работать без файлов cookie! Узнавайте что-то новое каждый день! programmerinterview.com/index.php/php-questions/…
dayuloli

конечно, они МОГУТ работать без файлов cookie, в зависимости от вашей конфигурации. Но ты должен знать, что делаешь. И для этого есть веская причина. Потому что это менее безопасно. и в случае, если вам нужно работать по какой-либо причине без файлов cookie. Вы должны как минимум настроить ini_set ('session.use_strict_mode', '1'); и обычно имеют короткое время сеанса и после входа пользователя в систему используйте session_regenerate_id (). Но имейте в виду, что если какой-то пользователь разместит ссылку на сайт на вашем сервере в форуме, люди, которые действительно щелкнут по этой ссылке, возьмут на себя сеанс. Возможно, проверка ip - тоже хорошая идея.
Michael

3

У меня была аналогичная проблема, хотя мой контекст был немного другим. У меня была локальная установка для разработки на машине с именем хоста windowsи IP-адресом 192.168.56.2.

Я мог получить доступ к системе, используя любое из:

После входа в систему мой PHP-код будет перенаправлять, используя:

header('http://windows/');

Если предыдущее доменное имя, используемое для доступа к системе, не было windows, данные сеанса будут потеряны. Я решил это, изменив код на:

header('http://'.$_SERVER['HTTP_HOST'].'/');

Теперь он работает независимо от того, какое локальное доменное имя или IP-адрес вводит пользователь.

Надеюсь, это может быть кому-то полезно.


3

Я столкнулся с этой проблемой на одной конкретной странице. Я устанавливал значения $ _SESSION на других страницах прямо перед перенаправлением, и все работало нормально. Но эта конкретная страница не работала.

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

function sessionKill(){

    session_destroy();

}

чтобы:

function sessionKill(){

    session_destroy();
    session_start();

}

И все заработало!


3

У меня была такая же проблема. Внезапно НЕКОТОРЫЕ из моих переменных сеанса не сохраняются на следующей странице. Проблема оказалась (в php7.1) в вашем заголовке не должно быть WWW, например https: // mysite . в порядке, https: //www.mysite . потеряет переменные сеанса страниц. Не все, только эта страница.


Это потому, что www.mysite.comон рассматривается как совершенно другой домен, чем blog.mysite.comили простоmysite.com
дайулоли

2

Я боролся с этим в течение нескольких дней, проверяя / пробуя все решения, но моя проблема заключалась в том, что я больше не звонил session_start();после перенаправления. Я просто предположил, что сеанс «все еще жив».

Так что не забывайте об этом!


Да! это тоже была моя проблема. Я думал, что начало сеанса PHP похоже на включение света во всем доме. Я не понимал, что вам нужно переключать переключатель для каждой комнаты, в которую вы входите.
Дейл Томпсон,

1

У меня была такая же проблема, и я нашел самый простой способ. Я просто перенаправил на перенаправленный .html с одной строкой JS

<!DOCTYPE html>
<html>
<script type="text/javascript">
<!--
window.location = "admin_index.php";
//–>
</script>
</html>

вместо PHP

header_remove();
header('Location: admin_login.php');
die;

Надеюсь, это поможет.

Любовь грамм


1

Если вы используете, session_set_cookie_params()вы можете проверить, передаете ли вы четвертый параметр $secureкак true. Если да, то вам нужно получить доступ к URL-адресу с помощью https.

Значение $securetrue означает, что сеанс доступен только в рамках защищенного запроса. Это может повлиять на вас больше локально, чем на стадии или в производственной среде.

Упоминаю об этом, потому что я потратил большую часть сегодняшнего дня, пытаясь найти эту проблему, и это то, что решило ее для меня. Меня только что добавили в этот проект, и никто не упомянул, что для этого нужен https.

Таким образом, вы можете использовать https локально или установить для $secureпараметра значение, FALSEа затем использовать http локально. Просто не забудьте вернуть его в значение true, когда будете вносить изменения.

В зависимости от вашего локального сервера, вы , возможно , придется редактировать DocumentRootв httpd-ssl.confсервера , так что локальный URL обслуживается по протоколу HTTPS.


1

Другая возможная причина:

Это место для хранения на моем сервере. Место на моем сервере заполнено. Итак, я удалил несколько файлов и папок со своего сервера и попробовал.

Сработало !!!

Я сохраняю свой сеанс в AWS Dynamo DB, но он по-прежнему ожидает, что на моем сервере останется место для обработки сеанса. Не знаю почему !!!


1

Если вы используете Laravel и столкнулись с этой проблемой, вам нужно сохранить данные сеанса перед перенаправлением.

session()->save();
// Redirect the user to the authorization URL.
header('Location: ' . $authorizationUrl);
exit;

0

У меня также была такая же проблема с неработающим перенаправлением, и я попробовал все решения, которые смог найти, мое перенаправление заголовка использовалось в форме.

Я решил это, поместив перенаправление заголовка на другую страницу php 'signin_action.php' и передав параметры переменных, которые я хотел, в параметрах url, а затем переназначил их в форме 'signin_action.php'.

signin.php

if($stmt->num_rows>0) {
$_SESSION['username'] = $_POST['username'];
echo '<script>window.location.href = "http://'.$root.'/includes/functions/signin_action.php?username='.$_SESSION['username'].'";</script>';
error_reporting(E_ALL);

signin_action.php

<?php
require('../../config/init.php');
$_SESSION['username'] = $_GET['username'];
if ($_SESSION['username']) {

echo '<script>window.location.href = "http://'.$root.'/user/index.php";</script>';
exit();
} else {
echo 'Session not set';
}

?>

Это не красивый обходной путь, но он сработал.


0

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

Однако я мог найти его в журналах ошибок Apache.


0

Просто для записи ... У меня была эта проблема, и после нескольких часов попыток проблема заключалась в том, что диск был заполнен, и сеансы php не могли быть записаны в каталог tmp ... поэтому, если у вас есть эта проблема, проверьте, что слишком...


Этот ответ сработал для меня. Мы запускаем образ машины Amazon с nginx. Похоже, существует ошибка в том, что папка сеанса не принадлежит правильному пользователю (в нашем случае www), поэтому выполнение chown -R www.wwwс папкой сеансов устраняет проблему.
Джошуа

0

Для меня Firefox сохранил идентификатор сеанса (PHPSESSID) в файле cookie, но Google Chrome использовал параметр GET или POST. Таким образом, вам нужно только убедиться, что возвращающий скрипт (для меня: PayPal checkout) фиксирует PHPSESSID в параметре url или POST.


0

Попробовав множество решений здесь, в SO и других блогах ... у меня сработало добавление .htaccess в корень моего сайта.

RewriteEngine on
RewriteCond %{HTTP_HOST} ^yoursitename.com$
RewriteRule ^.*$ "http\:\/\/www\.yoursitename\.com" [R=301,L]

0

Если вы используете Wordpress, мне пришлось добавить этот хук и запустить сеанс при инициализации:

function register_my_session() {
    if (!session_id()) {
        session_start();
    }
}
add_action('init', 'register_my_session');

0

У меня ничего не работало, но я нашел причину проблемы (и решил ее):

Проверьте файлы cookie своего браузера и убедитесь, что на разных поддоменах нет файлов cookie сеанса php (например, для « www.website.com » и для « website.com »).

Это было вызвано javascript, который неправильно использовал субдомен для установки файлов cookie и открытия страниц в окнах iframe.


0

Прежде всего, session_start()перед использованием $_SESSIONпеременной убедитесь, что вы вызываете .

Если вы отключили отчеты об ошибках, попробуйте включить и посмотреть результат.

ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);

Наиболее распространенные причины, не упомянутые в ответе @dayuloli:

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

  2. Каталог сеанса может быть недоступен для записи. Вы можете проверить это с помощьюis_writable(session_save_path())


0

У меня была такая же проблема, и я сошел с ума, ища в своем коде ответ. Наконец, я обнаружил, что мой хостинг недавно обновил версию PHP на моем сервере и неправильно настроил session_save_pathпараметр в php.iniфайле.

Итак, если кто-то прочитает это, пожалуйста, проверьте php.iniконфигурацию прежде всего.


0

Убедитесь, что session_write_closeон не вызывается между session_start()и при настройке сеанса.

session_start();

[...]

session_write_close();

[...]

$_SESSION['name']='Bob'; //<-- won't save

0

Теперь, когда GDPR стал нормой, люди, которые задают этот вопрос, вероятно, используют сценарий cookie. Что ж, этот сценарий вызвал у меня проблемы. Судя по всему, PHP использует cookie, вызываемый PHPSESSIDдля отслеживания сеанса. Если этот сценарий удалит его, вы потеряете свои данные.

Я использовал этот сценарий cookie . У него есть возможность включить «важные» файлы cookie. Я добавил PHPSESSIDв список, скрипт перестал удалять куки, и все снова заработало.

Вы, вероятно, могли бы включить некоторые настройки PHP, чтобы избежать использования PHPSESSID, но если ваш сценарий cookie является причиной проблемы, почему бы не исправить это .


0

Я исправил эту проблему после многих дней отладки, и все это произошло потому, что в моем URL-адресе возврата, полученном от PayPal Express Checkout, не было www. Chrome понимал, что с доменами следует обращаться одинаково, но в других браузерах это не так. При использовании сеансов / файлов cookie и абсолютных путей не забывайте "www"!


0

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


0

Сегодня у меня была эта проблема в проекте, и мне пришлось изменить этот параметр на false (или удалить строки, по умолчанию отключены):

ini_set( 'session.cookie_secure', 1 );

Это произошло потому, что реальный проект работает через http, а не только через https. Нашел дополнительную информацию в документации http://php.net/manual/en/session.security.ini.php


0
ini_set('session.save_path',realpath(dirname($_SERVER['DOCUMENT_ROOT']) . '/../session'));
session_start();

Слишком поздно отвечать, но это сработало для меня


0

Для меня это была ошибка разрешения, и это разрешило ее:

chown -R nginx: nginx / var / opt / remi / php73 / lib / php / сессия

Я несколько часов тестировал PHP, и последний тест, который я сделал, заключался в том, что я создал два файла session1.php и session2.php.

session1.php:

session_start();

$_SESSION["user"] = 123;

header("Location: session2.php");

session2.php:

session_start();

print_r($_SESSION);

и он печатал пустой массив.

На этом этапе я подумал, что это может быть проблема с сервером, и на самом деле это было так.

Надеюсь, это кому-то поможет.


1
Chown - это ПЛОХОЕ решение, так как оно будет изменено обратно на значение по умолчанию при обновлении пакета. См. Комментарии в конфигурации пула по умолчанию (www.conf). Правильный способ, если вы используете каталог, отличный от apache (например, / var / lib / php / nginx / session)
Реми Колле

Ты прав. Обновление пакета было причиной моей проблемы в первую очередь. Но поскольку это было сделано именно так, и мне нужно было какое-то быстрое решение, это помогло. Мой администратор SYS решил это, я не очень хорошо разбираюсь в Linux.
Temo
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.