Sesja PHP została utracona po przekierowaniu


135

Jak rozwiązać problem utraty sesji po przekierowaniu w PHP?

Ostatnio napotkałem bardzo częsty problem z utratą sesji po przekierowaniu. A po przeszukaniu tej strony nadal nie mogę znaleźć rozwiązania (chociaż to było najbliższe).

Aktualizacja

Znalazłem odpowiedź i pomyślałem, że opublikuję ją tutaj, aby pomóc każdemu, kto ma ten sam problem.


1
Pytanie brzmi, jak rozwiązać problem utraty sesji po przekierowaniu w PHP. Znalazłem już odpowiedź, po prostu publikując ją tutaj, aby inni ludzie wiedzieli. Ponieważ mojego rozwiązania nie ma w StackOverflow.
dayuloli

2
W porządku, ale to jest witryna kontroli jakości. Zadaj pytanie.
jeremy

Nie zauważyłem, że to od ciebie. Jednak ta strona jest przeznaczona do pytań, a nie do odpowiedzi na pytania, które już znasz.
Aris


24
@Aris To nieprawda, kiedy ludzie mają pytania dotyczące kodowania, przychodzą do StackOverflow po pomoc. Jeśli nie ma dostępnych odpowiedzi, nie mogą uzyskać pomocy, której potrzebują. Próbuję udzielić tej odpowiedzi.
dayuloli

Odpowiedzi:


212

Najpierw przeprowadź te zwykłe kontrole:

  1. Upewnij się, że session_start();jest wywoływana przed wywołaniem jakichkolwiek sesji. Więc bezpiecznym zakładem byłoby postawienie go na początku strony, bezpośrednio po <?phpdeklaracji otwarcia, przed czymkolwiek innym. Upewnij się również, że przed <?phpdeklaracją otwierającą nie ma spacji / tabulatorów .
  2. Po headerprzekierowaniu zakończ bieżący skrypt za pomocą exit();(inni również zasugerowali session_write_close();i session_regenerate_id(true)możesz też spróbować, ale ja bym użył exit();)
  3. Upewnij się, że pliki cookie są włączone w przeglądarce, której używasz do testowania.
  4. Upewnij register_globalssię, że jest wyłączone, możesz to sprawdzić w php.inipliku, a także za pomocą phpinfo(). Zapoznaj się z tym, jak go wyłączyć.
  5. Upewnij się, że nie usunąłeś ani nie opróżniłeś sesji
  6. Upewnij się, że klucz w twojej $_SESSIONsuperglobalnej tablicy nie został nigdzie nadpisany
  7. Upewnij się, że przekierowujesz do tej samej domeny. Zatem przekierowanie z a www.yourdomain.comdo yourdomain.comnie przenosi sesji do przodu.
  8. Upewnij się, że rozszerzenie pliku to .php(zdarza się!)

To są najczęstsze błędy, ale jeśli nie pomogły, problem najprawdopodobniej dotyczy Twojej firmy hostingowej. Jeśli wszystko działa, localhostale nie na serwerze zdalnym / testowym, najprawdopodobniej jest to przyczyną. Sprawdź więc bazę wiedzy swojego dostawcy usług hostingowych (wypróbuj także jego fora itp.). W przypadku firm takich jak FatCow i iPage wymagają one określenia session_save_path. Więc tak:

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

(Zastąp „ścieżkę do katalogu domowego” rzeczywistą ścieżką do katalogu domowego. Zwykle znajduje się ona w panelu sterowania (lub jego odpowiedniku), ale możesz też utworzyć test.phpplik w katalogu głównym i wpisać:

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

Bit przed „test.php” to ścieżka do katalogu domowego. I oczywiście upewnij się, że folder faktycznie istnieje w katalogu głównym. (Niektóre programy nie przesyłają pustych folderów podczas synchronizacji)


8
Bardzo dobrze napisane +1, jeśli wszystko zawiedzie, po prostu użyj plików cookie (losowo wygeneruj ciąg znaków i zapisz go w bazie danych i użyj go jako wartości pliku cookie).
Dave Chen

2
Przełączanie między http in https może być również problemem stackoverflow.com/questions/441496/…
dev.e.loper

4
Zauważ, że od php 5.4.0 register_globals zostało usunięte, więc nie będzie już powodować problemu
anthonygore

2
Sprawdź również dziennik błędów serwera WWW; w moim przypadku wystąpił błąd „Nie udało się zapisać danych sesji (plików). Sprawdź, czy bieżące ustawienie session.save_path jest poprawne”. Uprawnienia w katalogu save_path były nieprawidłowe.
timbonicus

Czy jest jakiś powód, dla którego moje sesje miałyby być przechowywane w innym miejscu niż session.save_path?
Justin

26

powinieneś użyć „exit” po wywołaniu nagłówka

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

Występuje błąd dla Gecko (np. Waterfox, Firefox, SeaMonkey), w którym jeśli są jakieś dane wyjściowe (np. echo ' ';) Lub spacje jakiegokolwiek rodzaju, całkowicie zignoruje nagłówek lokalizacji.
Jana

20

Wypróbowałem wszystkie możliwe rozwiązania, ale żadne nie zadziałało! Oczywiście korzystam z usługi hostingu współdzielonego.

W końcu udało mi się obejść problem, używając „względnego adresu URL” w nagłówku przekierowania!

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

anulował sesyjne pliki cookie

header("location: index.php")

działało jak urok!


8

Miałem ten sam problem. Pracowałem nad tym kilka godzin i doprowadzało mnie to do szału.

W moim przypadku problem polegał na wywołaniu 404 z powodu braku favicon.ico tylko w Chrome i Firefox. Inni nawigatorzy działali dobrze.


Chciałem tylko podziękować za tę odpowiedź, uświadomiłem sobie, że 404 żądania dotyczące obrazów były przekazywane przez Varnish do PHP bez żadnych plików cookie, a zatem nowe sesje były nieustannie tworzone. Może nigdy nie doszedłbym do tego bez ciebie.
Pascal Zając

Miałem ten sam problem, mój favicon.ico był przekierowywany (przekierowanie 302 z subdomeny do domeny głównej) i za każdym razem generowałem nową sesję. Wielkie dzięki!
simdrouin

5

Miałem ten sam problem. Nagle NIEKTÓRE z moich zmiennych sesji nie były przenoszone na następną stronę. Okazało się, że (w php7.1) lokalizacja nagłówka nie może zawierać WWW, np. Https: // mysite . jest w porządku, https: //www.mysite . utraci zmienne sesji tych stron. Nie wszystko, tylko ta strona.


To dlatego, że www.mysite.comjest postrzegana jako zupełnie inna domena niż blog.mysite.comlub po prostumysite.com
dayuloli

5

Kiedy używam ścieżki względnej "dir / file.php" z funkcją header () w działa dla mnie. Myślę, że sesja nie jest z jakiegoś powodu zapisywana, gdy przekierowujesz przy użyciu pełnego adresu 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

Miałem podobny problem, chociaż mój kontekst był nieco inny. Miałem lokalną konfigurację programistyczną na komputerze, którego nazwa hosta windowsi adres IP to192.168.56.2 .

Mogłem uzyskać dostęp do systemu za pomocą jednego z następujących sposobów:

Po zalogowaniu mój kod PHP przekierowałby za pomocą:

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

Gdyby poprzednia nazwa domeny używana do uzyskania dostępu do systemu nie była windows, dane sesji zostałyby utracone. Rozwiązałem to, zmieniając kod na:

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

Teraz działa niezależnie od nazwy domeny lokalnej lub adresu IP wprowadzonego przez użytkownika.

Mam nadzieję, że komuś się to przyda.


3

Natknąłem się na ten problem na jednej konkretnej stronie. Ustawiałem wartości $ _SESSION na innych stronach tuż przed przekierowaniem i wszystko działało dobrze. Ale ta konkretna strona nie działała.

W końcu zdałem sobie sprawę, że na tej konkretnej stronie niszczyłem sesję na początku strony, ale nigdy nie zaczynałam jej ponownie. Więc moja funkcja niszczenia zmieniła się z:

function sessionKill(){

    session_destroy();

}

do:

function sessionKill(){

    session_destroy();
    session_start();

}

I wszystko działało!


2

Długo mnie to martwiło (a ten post był świetny do znalezienia!), Ale dla każdego, kto nadal nie może uzyskać sesji między przekierowaniami stron do pracy ... Musiałem wejść do pliku php.ini i włączyć pliki cookie :

session.use_cookies = 1 

Myślałem, że sesje działają bez ciasteczek ... tak naprawdę wiem, że POWINNY ... ale to rozwiązało mój problem przynajmniej do czasu, gdy rozumiem, co może się dziać w szerszym kontekście.


Nie wiedziałem, że sesje mogą działać bez plików cookie! Dowiedz się czegoś nowego każdego dnia! programmerinterview.com/index.php/php-questions/ ...
dayuloli

oczywiście mogą działać bez plików cookie w zależności od konfiguracji. Ale powinieneś wiedzieć, co robisz. I mam ku temu dobry powód. Ponieważ jest mniej bezpieczny. i na wypadek, gdybyś musiał pracować z dowolnego powodu bez plików cookie. Powinieneś przynajmniej skonfigurować ini_set ('session.use_strict_mode', '1'); i ogólnie mają krótki czas sesji i po zalogowaniu użytkownika użyj session_regenerate_id (). Ale uważaj, jeśli jakiś użytkownik umieści na forum łącze do witryny na serwerze, osoby, które faktycznie klikną ten link, przejmą sesję. Może sprawdzenie adresu IP też jest dobrym pomysłem.
Michael

2

Zmagałem się z tym od dni, sprawdzając / próbując wszystkich rozwiązań, ale mój problem polegał na tym, że nie zadzwoniłem session_start(); po przekierowaniu ponownie. Po prostu założyłem, że sesja „wciąż żyje”.

Więc nie zapomnij o tym!


Tak! to był też mój problem. Wydawało mi się, że rozpoczęcie sesji PHP jest jak włączenie światła w całym domu. Nie zdawałem sobie sprawy, że musisz przekręcić przełącznik w każdym pokoju, do którego wchodzisz.
Dale Thompson

1

Miałem ten sam problem i znalazłem najłatwiejszy sposób. Po prostu przekierowałem do przekierowania .html z 1 linią JS

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

zamiast PHP

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

Mam nadzieję, że to pomoże.

Kocham Gram


1

Jeśli używasz, session_set_cookie_params()możesz chcieć sprawdzić, czy przekazujesz czwarty parametr $securejako true. Jeśli tak, musisz uzyskać dostęp do adresu URL za pomocą protokołu https.

Jeśli $secureparametr jest prawdziwy, oznacza to, że sesja jest dostępna tylko w ramach bezpiecznego żądania. Może to wpłynąć na Ciebie bardziej lokalnie niż w środowiskach scenicznych lub produkcyjnych.

Wspominając o tym, ponieważ spędziłem większość dnia na szukaniu tego problemu i właśnie to rozwiązało go dla mnie. Właśnie zostałem dodany do tego projektu i nikt nie wspomniał, że wymaga on https.

Możesz więc użyć protokołu https lokalnie lub ustawić $secureparametr na, FALSEa następnie użyć protokołu http lokalnie. Po prostu pamiętaj, aby ustawić ją z powrotem na prawdę, gdy wprowadzisz zmiany.

W zależności od lokalnego serwera może być konieczna edycja DocumentRootw pliku httpd-ssl.confserwera, aby lokalny adres URL był obsługiwany jako https.


1

Inny możliwy powód:

To jest moje miejsce na serwerze. Moje miejsce na dysku serwera zostało zapełnione. Więc usunąłem kilka plików i folderów na moim serwerze i spróbowałem.

Udało się !!!

Zapisuję sesję w AWS Dynamo DB, ale nadal oczekuje trochę miejsca na moim serwerze, aby przetworzyć sesję. Nie pewny dlaczego!!!


1

Jeśli używasz Laravel i napotykasz ten problem, musisz zapisać dane sesji przed przekierowaniem.

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

0

Miałem również ten sam problem z niedziałającym przekierowaniem i wypróbowałem wszystkie rozwiązania, które mogłem znaleźć, moje przekierowanie nagłówka było używane w formularzu.

Rozwiązałem to, umieszczając przekierowanie nagłówka na innej stronie php „signin_action.php” i przekazując parametry zmiennych przez, które chciałem w parametrach adresu URL, a następnie ponownie przypisując je w formularzu „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';
}

?>

Nie jest to piękne obejście, ale zadziałało.


0

U mnie błąd polegał na tym, że próbowałem zapisać w sesji obiekt, którego nie można było serializować, aby podczas próby zapisu sesji został wyrzucony wyjątek. Ale ponieważ cały mój kod obsługi błędów już przerwał jakąkolwiek operację, nigdy nie widziałem błędu.

Mogłem jednak znaleźć to w dziennikach błędów Apache.


0

Tak dla porządku ... miałem ten problem i po kilku godzinach próbowania wszystkiego problem polegał na tym, że dysk był pełny, a sesje php nie mogły zostać zapisane w katalogu tmp ... więc jeśli masz ten problem, sprawdź to też...


Ta odpowiedź zadziałała dla mnie. Uruchamiamy Amazon Machine Image z nginx. Wydaje się, że wystąpił błąd polegający na tym, że folder sesji nie jest własnością właściwego użytkownika (w naszym przypadku www), więc wykonanie chown -R www.wwww folderze sesji rozwiązuje problem.
Joshua,

0

Dla mnie Firefox zapisał identyfikator sesji (PHPSESSID) w pliku cookie, ale Google Chrome użył parametru GET lub POST. Musisz więc tylko upewnić się, że skrypt zwracający (dla mnie: paypal checkout) zatwierdzi PHPSESSID w parametrze url lub POST.


0

Po wypróbowaniu wielu rozwiązań tutaj na SO i innych blogach ... zadziałało dodanie .htaccess do katalogu głównego mojej witryny.

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

0

Jeśli używasz Wordpressa, musiałem dodać ten hook i rozpocząć sesję na init:

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

0

Nic nie działało, ale znalazłem przyczynę problemu (i rozwiązałem go):

Sprawdź pliki cookie swojej przeglądarki i upewnij się, że nie ma plików cookie sesji php w różnych subdomenach (np. Jedna dla „ www.website.com ” i jedna dla „ website.com ”).

Było to spowodowane przez skrypt javascript, który nieprawidłowo używał subdomeny do ustawiania plików cookie i otwierania stron w ramkach iframe.


0

Przede wszystkim upewnij się, że dzwonisz session_start()przed użyciem $_SESSIONzmiennej.

Jeśli wyłączyłeś raportowanie błędów, spróbuj go włączyć i zobacz wynik.

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

Najczęstsze przyczyny, które nie zostały wymienione w odpowiedzi @ dayuloli:

  1. Problem z miejscem na dysku. Upewnij się, że miejsce na dysku nie jest pełne, potrzebujesz trochę miejsca do przechowywania plików sesji.

  2. Katalog sesji może nie być zapisywalny. Możesz to sprawdzićis_writable(session_save_path())


0

Miałem ten sam problem i oszalałem, szukając odpowiedzi w swoim kodzie. W końcu odkryłem, że mój hosting niedawno zaktualizował wersję PHP na moim serwerze i nie ustawił poprawnie session_save_pathparametru w php.inipliku.

Więc jeśli ktoś to przeczyta, sprawdź php.ininajpierw konfigurację.


0

Upewnij się, że session_write_closenie jest wywoływany pomiędzy session_start()i podczas ustawiania sesji.

session_start();

[...]

session_write_close();

[...]

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

0

Teraz, gdy RODO jest już rzeczą, osoby odwiedzające to pytanie prawdopodobnie używają skryptu cookie. Cóż, ten skrypt spowodował dla mnie problem. Najwyraźniej PHP wykorzystuje plik cookie o nazwiePHPSESSID do śledzenia sesji. Jeśli ten skrypt go usunie, utracisz swoje dane.

Użyłem tego skryptu cookie . Posiada opcję włączenia „niezbędnych” plików cookie. dodałemPHPSESSID do listy, skrypt przestał usuwać ciasteczko i wszystko znów zaczęło działać.

Prawdopodobnie możesz włączyć niektóre ustawienia PHP, aby uniknąć używania PHPSESSID, ale jeśli przyczyną problemu jest skrypt cookie, dlaczego nie naprawić tego .


0

Naprawiłem ten problem po wielu dniach debugowania, a to wszystko dlatego, że mój zwrotny adres URL pochodzący z PayPal Express Checkout nie miał „www”. Chrome uznał, że domeny powinny być traktowane tak samo, ale inne przeglądarki czasami nie. Korzystając z sesji / plików cookie i ścieżek bezwzględnych, nie zapomnij o „www”!


0

Naprawiłem, dając grupie uprawnienia do zapisu do ścieżki, w której PHP przechowuje pliki sesji. Możesz znaleźć ścieżkę sesji za pomocą funkcji session_save_path ().


0

Dzisiaj miałem ten problem w projekcie i musiałem zmienić ten parametr na false (lub usunąć linie, domyślnie jest wyłączona):

ini_set( 'session.cookie_secure', 1 );

Stało się tak, ponieważ rzeczywisty projekt działa przez http, a nie tylko https. Więcej informacji można znaleźć w dokumentach http://php.net/manual/en/session.security.ini.php


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

Za późno na odpowiedź, ale to zadziałało


0

Dla mnie to był błąd uprawnień i to rozwiązało problem:

chown -R nginx: nginx / var / opt / remi / php73 / lib / php / session

Testowałem kilka godzin na PHP, a ostatnim testem, który zrobiłem, było utworzenie dwóch plików session1.php i session2.php.

session1.php:

session_start();

$_SESSION["user"] = 123;

header("Location: session2.php");

session2.php:

session_start();

print_r($_SESSION);

i wypisuje pustą tablicę.

W tym momencie pomyślałem, że może to być problem z serwerem i faktycznie tak było.

Mam nadzieję, że to komuś pomoże.


1
Chown jest złym rozwiązaniem, ponieważ zostanie przywrócony do wartości domyślnej podczas aktualizacji pakietu. Zobacz komentarze w domyślnej konfiguracji puli (www.conf). Właściwy sposób, jeśli używasz innego katalogu niż apache (np: / var / lib / php / nginx / session)
Remi Collet

Masz rację. aktualizacja pakietu była przyczyną mojego problemu w pierwszej kolejności. Ale ponieważ tak to zostało zrobione i potrzebowałem szybkiego rozwiązania, które pomogło. Mój administrator SYS rozwiązał ten problem, nie radzę sobie dobrze z Linuksem.
temo
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.