Sessioni PHP tra sottodomini


92

Sto cercando di impostare quanto segue:

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

Se l'utente visita sub1.example.como sub2.example.come non ha effettuato l'accesso, viene reindirizzato a auth.example.come può accedere.

sub1.example.come sub2.example.comsono due applicazioni separate ma utilizzano le stesse credenziali.

Ho provato a impostare quanto segue nel mio php.ini:

session.cookie_domain = ".example.com"

ma non sembra passare le informazioni da un dominio all'altro.

[Modificare]

Ho provato quanto segue:

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);

Gli ID di sessione sono esattamente gli stessi, ma quando eseguo il dump della $_SESSIONvariabile non mostra entrambe le chiavi, ma qualunque chiave ho impostato in ogni dominio.



1
Ho quasi la stessa configurazione (ho impostato il dominio dei cookie di sessione con una chiamata a "session_set_cookie_params") e funziona bene.
Milen A. Radev

Ecco bella funzione che le opere stackoverflow.com/questions/2835486/...
boksiora

Risposte:


134

Non so se il problema persiste, ma mi sono imbattuto nello stesso problema e l'ho risolto impostando un nome di sessione prima di chiamare session_set_cookie_params():

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

Non ho cambiato nulla nel mio php.inima ora funziona tutto bene.


10
Confermo, risolve il problema. Sono stanco di avere la mia risposta lì: stackoverflow.com/questions/4948340/… . Ma l'ho trovato qui.
Roman

5
Funziona perfettamente! Ho cercato per anni questo. È stato quello $some_name = session_name("some_name");che l'ha fatto. Grazie e voto positivo.
Kit

4
Aggiungere session_name("domain");era l'ingrediente mancante anche per me. La documentazione su php.net relativa a queste impostazioni di sessione manca. Ci sono post della comunità su php.net che indicano che session.name deve essere definito prima che le modifiche a session_set_cookie_params () possano essere applicate.
David Carroll

3
Sì. confermato. uno carino stava girando in tondo per secoli lì;)
Daithí

1
NOTA ... ho dovuto chiudere il browser e riavviarlo per farlo funzionare sul server di vita. Tralascia qualsiasi ini_set("session.cookie_domain", ".domain.com");causa che causava la creazione di un nuovo ID di sessione ad ogni aggiornamento.
Daithí

24

Una cosa che può misteriosamente impedire la lettura dei dati di sessione su un sottodominio, nonostante i cookie siano impostati correttamente .example.comè la patch PHP Suhosin. Puoi avere tutto configurato correttamente, come negli esempi nella domanda, e non può funzionare.

Disattiva le seguenti impostazioni di sessione di Suhosin e sei di nuovo in attività:

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

5

Prova a usare:

session.cookie_domain = "example.com"

Invece di:

session.cookie_domain = ".example.com"

Nota il periodo mancante all'inizio.

Fai attenzione a usarlo, però, perché non è supportato da tutti i browser.


9
Quali browser non sono supportati?
gawpertron

10
cosa deve supportare il browser qui? questa è un'azione lato server.
Kuf

4

Ho avuto questo problema esatto: volevo che i valori di sessione creati su x.example.local fossero disponibili su example.local e viceversa.

Tutte le soluzioni che ho trovato dicevano di cambiare il dominio della sessione utilizzando php_value session.cookie_domain .example.localin .htaccess (o tramite php.ini o tramite ini_set).

Il problema era che stavo impostando session.cookie_domainper tutti i sottodomini (finora ok) ma anche per il dominio principale. L'impostazione del session.cookie_domaindominio principale è apparentemente un no-no.

Fondamentalmente il modo in cui ha funzionato per me:

  • impostare session.cookie_domainper TUTTI I SOTTOMINI.
  • non impostarlo per il DOMAIN principale

Oh sì, assicurati che il dominio abbia un TLD (nel mio caso .local). Il protocollo HTTP non consente la memorizzazione di cookie / sessioni su un dominio senza .tld (cioè localhost non funzionerà, ma stuff.localhost lo farà).

MODIFICA : assicurati inoltre di cancellare sempre i cookie del browser durante il test / debug delle sessioni tra i sottodomini. Se non lo fai, il tuo browser invierà sempre il vecchio cookie di sessione che probabilmente non ha ancora impostato il cookie_domain corretto. Il server farà rivivere la vecchia sessione e quindi otterrai risultati falsi negativi. (in molti post viene menzionato l'uso di session_name ('stuff') per lo stesso identico effetto)


3

L'ho risolto in questo modo

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

Perché stavo lavorando su localhost

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

non funzionava , vede .localhost come toplevel invece di .com / .local / ... (sospetto)


Risolto anche il problema per la mia macchina - Ubuntu 14.04
dennis

3

Ho confermato La risposta di joreon è corretta. Non posso commentare perché la mia reputazione non è sufficiente quindi inserisco il mio commento qui.

Definisci la costante in un file di configurazione. Se vuoi cambiarlo, non è necessario modificare interi file.

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

Il nome della sessione non può essere composto da sole cifre, deve essere presente almeno una lettera. In caso contrario, ogni volta viene generato un nuovo ID di sessione.

Usa il codice seguente per iniziare a usare session

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

Sto usando questa funzione:

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

Usalo su ogni dominio / sottodominio:

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

Il percorso per session.save_pathpuò essere diverso per il tuo caso, ma dovrebbe essere lo stesso per ogni dominio / sottodominio. Non è sempre vero per impostazione predefinita.


1

Usa questo, funziona:

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

sembra che stia impostando il cookie per il tld ... o mi manca qualcosa?
chacham15

1

Uso combinato delle sessioni di cookie del sottodominio e del dominio principale

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

Ho testato le opere

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

example.com/sessionview.php // 123

- Codici

<?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

Ho l'idea che tu non voglia qualcosa come OpenID, come suggerisce Joel, ma che tu voglia avere accesso ai dati della sessione su più domini.

L'unica possibilità che posso pensare come una soluzione per quel problema è memorizzare i dati della sessione in un database ed estrarli da quel database.


Bene, mentre l'autenticazione è una parte di ciò che voglio fare, mi interessano anche i dati della sessione che vengono memorizzati mentre l'utente sta lavorando.
dragonmantank


0

Non posso parlare per altre versioni di PHP, ma nella 5.6.6, la semplice impostazione del session.cookie_domainvalore nel php.inifile ha fatto il trucco per consentire a tutti i miei sottodomini su iPage di condividere lo stesso insieme di variabili di sessione.

Assicurati di rimuovere tutti i cookie esistenti relativi al tuo dominio dal browser per eseguire il test.

session.cookie_domain = '.yourdomainname.example'

Oh, non so se fa qualche differenza, ma sto anche usando l'avvio automatico della sessione.

session.auto_start = 1

0

Prova semplicemente a utilizzare il codice seguente appena sopra il session_start()metodo

$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

Ho letto tutte le risposte sopra, penso che la mia risposta sia utile per le persone che cercano su Google questo:

  • assicurarsi che i browser inviino il cookie di sessione ai server (del dominio e dei sottodomini), impostare il dominio del cookie di sessione come .example.com.

  • Assicurati che PHP trovi la "destinazione" giusta per ripristinare la variabile di sessione:

    • Se dominio e sottodomini puntano alla stessa macchina (forse host virtuali diversi), assicurati che session_save_pathsia lo stesso per tutti (ho testato)
    • Se dominio e sottodomini puntano a macchine diverse, l'archiviazione comune (come il database) è la migliore per salvare e ripristinare i dati di sessione (non ho ancora testato). Usa session_set_save_handlerper farlo.

0

So che questo è vecchio ma funziona bene per me con più domini e sottodomini sulla stessa scatola.

<?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
A quale domanda stai rispondendo? E in che modo questo migliora / migliora le altre 9 risposte?
random_user_name

0

Uso :

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

-2

Una soluzione rapida e sporca è usare questo per il tuo reindirizzamento:

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

questo aggiungerà qualcosa sulla falsariga di ?PHPSESSID=etnm7kbuf5lg0r6tv7je6ehtn4all'URL, che dice a PHP l'id di sessione che dovrebbe usare.


3
Inoltre lo lascia altamente vulnerabile al furto di sessione :) Il problema non è con gli ID di sessione che non corrispondono (lo sono, vedi il mio post aggiornato), ma con i dati che non si spostano tra i domini.
dragonmantank

D'accordo, questo è altamente vulnerabile lasciando l'ID di sessione nella stringa di query.
Ian Jamieson

4
I cookie vengono inviati anche come testo normale, questo non apre strade che non fossero già aperte. Non sto dicendo che sia una buona soluzione, ma non è meno sicura dell'utilizzo dei cookie.
sakabako

1
È meno sicuro nel senso che gli utenti possono essere (indotti a) condividere il loro URL e quindi condividere il loro ID di sessione attivo. È molto meno probabile che un utente condivida involontariamente il cookie dell'ID di sessione.
Bastiaan ten Klooster
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.