Sesje PHP w subdomenach


92

Próbuję skonfigurować następujące elementy:

auth.example.com
sub1.example.com
sub2.example.com

Jeśli użytkownik odwiedza witrynę sub1.example.comlub sub2.example.comnie jest zalogowany, zostaje przekierowany auth.example.comi może się zalogować.

sub1.example.comi sub2.example.comsą to dwie oddzielne aplikacje, ale używają tych samych poświadczeń.

Próbowałem ustawić następujące w moim php.ini:

session.cookie_domain = ".example.com"

ale wydaje się, że nie przekazuje informacji z jednej domeny do drugiej.

[Edytować]

Próbowałem następujących rzeczy:

sub1.example.com/test.php

session_set_cookie_params(0, '/', '.example.com');
session_start();
print session_id() . "<br>";
$_SESSION['Regsitered'] = 1;
echo '<a href="http://auth.example.com/test.php">Change Sites</a>'

auth.example.com/test.php

session_set_cookie_params(0, '/', '.example.com');
session_start();
print session_id() . "<br>";
$_SESSION['Checked'] = 1;
print_r($_SESSION);

Identyfikatory sesji są dokładnie takie same, ale kiedy zrzucam $_SESSIONzmienną, nie pokazuje ona obu kluczy, tylko ten, który ustawiłem w każdej domenie.


Musisz również włączyć to w swoim kodzie, patrz http://us2.php.net/manual/en/function.session-set-cookie-params.php
Residuum

1
Mam prawie taką samą konfigurację (ustawiłem domenę cookie sesji za pomocą wywołania „session_set_cookie_params”) i działa dobrze.
Milen A. Radev

Oto fajna funkcja, która działa stackoverflow.com/questions/2835486/ ...
boksiora

Odpowiedzi:


134

Nie wiem, czy problem nadal istnieje, ale właśnie napotkałem ten sam problem i rozwiązałem go ustawiając nazwę sesji przed wywołaniem session_set_cookie_params():

$some_name = session_name("some_name");
session_set_cookie_params(0, '/', '.example.com');
session_start();

Nic nie zmieniłem w moim, php.iniale teraz wszystko działa dobrze.


10
Potwierdzam, to rozwiązuje problem. Zmęczyłem się, aby uzyskać tam odpowiedź: stackoverflow.com/questions/4948340/… . Ale znalazłem to tutaj.
Roman

5
Działa idealnie! Szukałem tego od wieków. To on $some_name = session_name("some_name");to zrobił. Dziękuję i zagłosuj.
Kit

4
Dodanie również session_name("domain");było dla mnie brakującym składnikiem. Brakuje dokumentacji na php.net dotyczącej tych ustawień sesji. Istnieją posty społeczności na php.net, które wskazują, że nazwa session.name musi zostać zdefiniowana przed zastosowaniem zmian w session_set_cookie_params ().
David Carroll,

3
tak. Potwierdzony. fajny
krążył

1
UWAGA ... musiałem zamknąć przeglądarkę i uruchomić ją ponownie, aby działała na serwerze życia. Pomiń każdą ini_set("session.cookie_domain", ".domain.com");przyczynę, która powodowała, że ​​tworzył nowy identyfikator sesji przy każdym odświeżaniu.
Daithí

24

Jedną z rzeczy, która może w tajemniczy sposób uniemożliwić odczyt danych sesji z subdomeny, pomimo poprawnego ustawienia plików cookie, .example.comjest łatka PHP Suhosin. Możesz mieć wszystko poprawnie skonfigurowane, jak na przykładach w pytaniu, i po prostu może nie działać.

Wyłącz następujące ustawienia sesji Suhosin i wrócisz do pracy:

suhosin.session.cryptua = Off 
suhosin.session.cryptdocroot = Off

5

Spróbuj użyć:

session.cookie_domain = "example.com"

Zamiast:

session.cookie_domain = ".example.com"

Zwróć uwagę na brakujący okres na początku.

Uważaj jednak, ponieważ nie jest obsługiwany przez wszystkie przeglądarki.


9
Które przeglądarki nie są obsługiwane?
gawpertron

10
jakie wsparcie przeglądarki musi tutaj zrobić? jest to akcja po stronie serwera.
Kuf

4

Miałem dokładnie ten problem - chciałem, aby wartości sesji utworzone na x.example.local były dostępne na example.local i na odwrót.

Wszystkie rozwiązania, które znalazłem, mówiły, że zmieniają domenę sesji za pomocą php_value session.cookie_domain .example.local.htaccess (lub przez php.ini lub przez ini_set).

Problem polegał na tym, że ustawiałem session.cookie_domaindla wszystkich subdomen (do tej pory ok), ale także dla domeny głównej. Ustawienie session.cookie_domainna domenie głównej najwyraźniej nie jest możliwe.

Zasadniczo sposób, w jaki to zadziałało dla mnie:

  • ustaw session.cookie_domaindla WSZYSTKICH PODDOMEN.
  • nie ustawiaj go dla głównej DOMENY

O tak, upewnij się, że domena ma domenę TLD (w moim przypadku .local). Protokół HTTP nie pozwala na przechowywanie plików cookie / sesji w domenie bez .tld (tzn. Localhost nie będzie działać, ale stuff.localhost tak).

EDYTUJ : Upewnij się również, że zawsze usuwasz pliki cookie przeglądarki podczas testowania / debugowania sesji w subdomenach. Jeśli tego nie zrobisz, Twoja przeglądarka zawsze będzie wysyłać stary plik cookie sesji, który prawdopodobnie nie ma jeszcze ustawionego prawidłowego pliku cookie_domain. Serwer ożywi starą sesję i uzyskasz fałszywie negatywne wyniki. (w wielu postach jest mowa o używaniu session_name ('stuff') dla dokładnie tego samego efektu)


3

Rozwiązałem to w ten sposób

ini_set('session.cookie_domain', '.testdomain.example');
session_start();

Ponieważ pracowałem na localhost

ini_set('session.cookie_domain', '.localhost');

nie działał , widzi .localhost jako najwyższy poziom zamiast .com / .local / ... (podejrzewam)


Naprawiono to również dla mojej maszyny - Ubuntu 14.04
dennis

3

Potwierdziłem. Odpowiedź joreona jest prawidłowa. Nie mogę komentować, ponieważ moja reputacja nie wystarczy, więc zamieszczam tutaj komentarz.

Zdefiniuj stałą w pliku konfiguracyjnym. Jeśli chcesz to zmienić, nie musisz modyfikować całych plików.

define('ROOT_DOMAIN',   'mysite.example');
define('PHP_SESSION_NAME', 'MYSITE'); 

Nazwa sesji nie może składać się tylko z cyfr, musi być obecna przynajmniej jedna litera. W przeciwnym razie za każdym razem generowany jest nowy identyfikator sesji.

Użyj poniższego kodu, aby rozpocząć korzystanie z sesji

session_name(PHP_SESSION_NAME);
session_set_cookie_params(0, '/', '.' . ROOT_DOMAIN);
session_start();

Używam tej funkcji:

function load_session() {
    if (session_status() == PHP_SESSION_NONE) {
        session_name(PHP_SESSION_NAME);
        session_set_cookie_params(0, '/', '.' . ROOT_DOMAIN);
        session_start();
    } elseif (session_name() != PHP_SESSION_NAME) {
        session_destroy();
        session_name(PHP_SESSION_NAME);
        session_set_cookie_params(0, '/', '.' . ROOT_DOMAIN);
        session_start();
    }
}
load_session(); // put it in anywhere you want to use session

2

Używaj go w każdej domenie / subdomenie:

session_name('name');
ini_set('session.cookie_domain', '.example.com');
ini_set('session.save_path', '/var/lib/php/session');
session_start();

Ścieżka do session.save_pathmoże być inna w Twoim przypadku, ale powinna być taka sama w każdej domenie / subdomenie. Nie zawsze jest to prawda.


1

Użyj tego, to działa:

ini_set('session.cookie_domain', 
    substr($_SERVER['SERVER_NAME'],strpos($_SERVER['SERVER_NAME'],"."),100));

wygląda na to, że ustawia plik cookie dla tld ... czy czegoś mi brakuje?
chacham15

1

Łączone użycie sesji plików cookie domeny podrzędnej i domeny głównej

Ratunek: http://php.net//manual/tr/function.session-set-cookie-params.php

Sprawdziłem działa

sub.example.com/sessionadd.php?id=123

example.com/sessionview.php // 123

- Kody

<?php 
$currentCookieParams = session_get_cookie_params(); 

$rootDomain = '.example.com'; 

session_set_cookie_params( 
    $currentCookieParams["lifetime"], 
    $currentCookieParams["path"], 
    $rootDomain, 
    $currentCookieParams["secure"], 
    $currentCookieParams["httponly"] 
); 

session_name('mysessionname'); 
session_start(); 

setcookie($cookieName, $cookieValue, time() + 3600, '/', $rootDomain); 
?>

0

Wydaje mi się, że nie chcesz czegoś takiego jak OpenID, jak sugeruje Joel, ale chcesz mieć dostęp do danych sesji w wielu domenach.

Jedyną możliwością, którą mogę sobie wyobrazić jako rozwiązanie tego problemu, jest przechowywanie danych sesji w bazie danych i wyciąganie ich z tej bazy danych.


Racja, chociaż uwierzytelnianie jest częścią tego, co chcę zrobić, interesują mnie również dane sesji, które są przechowywane podczas pracy użytkownika.
dragonmantank


0

Nie mogę wypowiadać się na temat innych wersji PHP, ale w 5.6.6 samo ustawienie session.cookie_domainwartości w php.inipliku załatwiło sprawę, pozwalając wszystkim moim subdomenom na iPage współdzielić ten sam zestaw zmiennych sesji.

Pamiętaj, aby usunąć wszystkie istniejące pliki cookie związane z Twoją domeną z przeglądarki, aby przetestować.

session.cookie_domain = '.yourdomainname.example'

Och, nie wiem, czy to robi jakąkolwiek różnicę, ale używam też autostartu sesji.

session.auto_start = 1

0

Po prostu spróbuj użyć następującego kodu powyżej session_start()metody

$sess_life_time = 21600; //in seconds
$sess_path = "/";
$sess_domain = ".example.com";
$sess_secure = true; // if you have secured session
$sess_httponly = true; // httponly flag

session_set_cookie_params($sess_life_time, $sess_path, $sess_domain, $sess_secure, $sess_httponly);

0

Przeczytałem wszystkie powyższe odpowiedzi, myślę, że moja odpowiedź jest pomocna dla osób szukających tego w Google:

  • upewnij się, że przeglądarki wysyłają plik cookie sesji z powrotem do serwerów (domeny i subdomen), ustaw domenę plików cookie sesji jako .example.com.

  • Upewnij się, że PHP znajduje właściwy „cel”, aby przywrócić zmienną sesji:

    • Jeśli domena i subdomeny wskazują na tę samą maszynę (być może różne wirtualne hosty), upewnij się session_save_path jest taka sama dla wszystkich (testowałem)
    • Jeśli domena i subdomeny wskazują różne maszyny, wspólny magazyn (taki jak baza danych) jest najlepszy do zapisywania i przywracania danych sesji (jeszcze nie testowałem). Użyj session_set_save_handlerdo tego.

0

Wiem, że to jest stare, ale działa dobrze w przypadku wielu domen i subdomen w tym samym pudełku.

<?php
define('site_domain','example.com');
session_set_save_handler('_open',
                         '_close',
                         '_read',
                         '_write',
                         '_destroy',
                         '_clean');

function _open(){

    global $_sess_db;

$db_user = 'user';
$db_pass = 'pass';
$db_host = 'localhost';

if ($_sess_db = mysql_connect($db_host, $db_user, $db_pass)){

    return mysql_select_db('database', $_sess_db);

}

return false;

}

function _close(){

    global $_sess_db;
    return mysql_close($_sess_db);

}

function _read($id){

    global $_sess_db;
    $id = mysql_real_escape_string($id);
    $domain = mysql_real_escape_string(site_domain);
    $agent = mysql_real_escape_string(isset($_SERVER['HTTP_USER_AGENT']));

    $sql = "SELECT data
    FROM sessions
    WHERE id = '$id' AND domain = '$domain' AND agent = '$agent'";

     if ($result = mysql_query($sql, $_sess_db)){

         if (mysql_num_rows($result)){
             $record = mysql_fetch_assoc($result);
             return $record['data'];
        }

    }

    return '';

}

function _write($id, $data){

    global $_sess_db;
    $access = time();

    $id = mysql_real_escape_string($id);
    $access = mysql_real_escape_string($access);
    $data = mysql_real_escape_string($data);
    $domain = mysql_real_escape_string(site_domain);
    $agent = mysql_real_escape_string(isset($_SERVER['HTTP_USER_AGENT']));

    $sql = "REPLACE INTO sessions
    VALUES ('$id', '$access', '$data', '$domain', '$agent')";

    return mysql_query($sql, $_sess_db);

}

function _destroy($id){

    global $_sess_db;
    $id = mysql_real_escape_string($id);
    $domain = mysql_real_escape_string(site_domain);
    $agent = mysql_real_escape_string(isset($_SERVER['HTTP_USER_AGENT']));

    $sql = "DELETE FROM sessions
    WHERE id = '$id' AND domain = '$domain' AND agent = '$agent'";

    return mysql_query($sql, $_sess_db);

}

function _clean($max){

    global $_sess_db;
    $old = time() - $max;
    $old = mysql_real_escape_string($old);
    $domain = mysql_real_escape_string(site_domain);
    $agent = mysql_real_escape_string(isset($_SERVER['HTTP_USER_AGENT']));

    $sql = "DELETE FROM sessions
    WHERE  access < '$old' AND domain = '$domain' AND agent = '$agent'";

    return mysql_query($sql, $_sess_db);

}

?>


6
Na jakie pytanie odpowiadasz? I jak to poprawia / wzmacnia 9 innych odpowiedzi?
random_user_name

0

Posługiwać się :

session_name("put_a_session_name");
session_start([
  "cookie_domain" => ".example.com",
  "cookie_path" => "/"
]);

-2

Szybkim i brudnym rozwiązaniem jest użycie tego do przekierowania:

header( $url.'?'.session_name().'='.session_id() );

doda to ?PHPSESSID=etnm7kbuf5lg0r6tv7je6ehtn4do adresu URL coś , co informuje PHP o identyfikatorze sesji, którego powinien użyć.


3
To także czyni go wysoce podatnym na kradzież sesji :) Problem nie polega na tym, że identyfikatory sesji nie pasują (są, zobacz mój zaktualizowany post), ale z danymi nie przemieszczającymi się między domenami.
dragonmantank

Zgoda, jest to wysoce podatne na pozostawienie identyfikatora sesji w ciągu zapytania.
Ian Jamieson

4
Pliki cookie są również wysyłane jako zwykły tekst, co nie otwiera żadnych ścieżek, które nie były jeszcze otwarte. Nie twierdzę, że to dobre rozwiązanie, ale jest nie mniej bezpieczne niż używanie plików cookie.
sakabako

1
Jest mniej bezpieczny w tym sensie, że użytkownicy mogą (oszukiwać) udostępniać swój adres URL, a tym samym udostępniać swój identyfikator aktywnej sesji. Jest znacznie mniej prawdopodobne, że użytkownik niechcący udostępni plik cookie z identyfikatorem sesji.
Bastiaan ten Klooster
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.