Sesiones PHP en subdominios

92

Estoy intentando configurar lo siguiente:

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

Si el usuario visita sub1.example.como sub2.example.comy no ha iniciado sesión, se le redirige auth.example.comy puede iniciar sesión.

sub1.example.comy sub2.example.comson dos aplicaciones independientes pero utilizan las mismas credenciales.

Intenté configurar lo siguiente en mi php.ini:

session.cookie_domain = ".example.com"

pero no parece estar pasando la información de un dominio a otro.

[Editar]

Intenté lo siguiente:

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

Los ID de sesión son exactamente los mismos, pero cuando descargo la $_SESSIONvariable, no muestra ambas claves, solo cualquier clave que establezca en cada dominio.

dragonmantank
fuente
También debe habilitarlo en su código, consulte http://us2.php.net/manual/en/function.session-set-cookie-params.php
Residuum
1
Tengo casi la misma configuración (configuré el dominio de cookies de sesión con una llamada a "session_set_cookie_params") y funciona bien.
Milen A. Radev
Aquí hay una buena función que funciona stackoverflow.com/questions/2835486/…
boksiora

Respuestas:

134

No sé si el problema aún existe, pero me encontré con el mismo problema y lo resolví estableciendo un nombre de sesión antes de llamar session_set_cookie_params():

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

No he cambiado nada en mi, php.inipero ahora todo está funcionando bien.

jeroen
fuente
10
Confirmo, soluciona el problema. Me cansé de obtener mi respuesta allí: stackoverflow.com/questions/4948340/… . Pero lo encontré aquí.
Roman
5
¡Funciona perfecto! He estado buscando durante años para esto. Fue el $some_name = session_name("some_name");que lo hizo. Gracias y voto a favor.
Kit
4
Agregar session_name("domain");era el ingrediente que me faltaba también. Falta la documentación en php.net con respecto a estas configuraciones de sesión. Hay publicaciones de la comunidad en php.net que indican que session.name debe definirse antes de que se puedan aplicar los cambios a session_set_cookie_params ().
David Carroll
3
Sí. confirmado. agradable estuvo dando vueltas en círculos durante años allí;)
Daithí
1
NOTA ... tuve que cerrar mi navegador y reiniciar para que funcione en el servidor de vida. Deje de lado cualquier ini_set("session.cookie_domain", ".domain.com");causa que esto causaba que creara una nueva identificación de sesión con cada actualización.
Daithí
24

Una cosa que puede evitar misteriosamente que se lean los datos de la sesión en un subdominio, a pesar de que las cookies estén configuradas correctamente .example.comes el parche PHP Suhosin. Puede tener todo configurado correctamente, según los ejemplos de la pregunta, y simplemente no puede funcionar.

Desactive la siguiente configuración de sesión de Suhosin y estará de vuelta en el negocio:

suhosin.session.cryptua = Off 
suhosin.session.cryptdocroot = Off
dibujó
fuente
5

Intente usar:

session.cookie_domain = "example.com"

En vez de:

session.cookie_domain = ".example.com"

Tenga en cuenta el período que falta al principio.

Sin embargo, tenga cuidado al usar esto porque no es compatible con todos los navegadores.

George Claghorn
fuente
9
¿Qué navegadores no son compatibles?
gawpertron
10
¿Qué soporte de navegador tiene que hacer aquí? esta es una acción del lado del servidor.
Kuf
4

Tenía este problema exacto: quería que los valores de sesión creados en x.example.local estuvieran disponibles en example.local y viceversa.

Todas las soluciones que encontré decían cambiar el dominio de sesión usando php_value session.cookie_domain .example.localen .htaccess (o vía php.ini o vía ini_set).

El problema fue que estaba configurando session.cookie_domainpara todos los subdominios (hasta ahora bien) pero también para el dominio principal. Establecer el session.cookie_domaindominio principal es aparentemente un no-no.

Básicamente la forma en que funcionó para mí:

  • configure el session.cookie_domainpara TODOS LOS SUBDOMINIOS.
  • no lo configure para el DOMINIO principal

Oh, sí, asegúrese de que el dominio tenga un TLD (en mi caso .local). El protocolo HTTP no permite que las cookies / sesiones se almacenen en un dominio sin .tld (es decir, localhost no funcionará, pero stuff.localhost sí lo hará).

EDITAR : También asegúrese de borrar siempre las cookies de su navegador mientras prueba / depura sesiones en subdominios. Si no lo hace, su navegador siempre enviará la cookie de sesión anterior, que probablemente aún no tenga el cookie_domain correcto configurado. El servidor revivirá la sesión anterior y, por lo tanto, obtendrá resultados negativos falsos. (en muchas publicaciones se menciona usar session_name ('cosas') para obtener exactamente el mismo efecto)

Valentin Florea
fuente
3

Lo resolví así

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

Porque estaba trabajando en localhost

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

no estaba funcionando , ve .localhost como el nivel superior en lugar de .com / .local / ... (sospecho)

xtds
fuente
También lo arreglé para mi máquina - Ubuntu 14.04
dennis
3

He confirmado. la respuesta de joreon es correcta. No puedo comentar porque mi reputación no es suficiente, así que publico mi comentario aquí.

Defina la constante en un archivo de configuración. Si desea cambiarlo, no es necesario modificar archivos completos.

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

El nombre de la sesión no puede constar solo de dígitos, debe estar presente al menos una letra. De lo contrario, se genera una nueva identificación de sesión cada vez.

Use el siguiente código para comenzar a usar la sesión

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

Estoy usando esta función:

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
Terry Lin
fuente
2

Úselo en cada dominio / subdominio:

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

La ruta para session.save_pathpuede ser diferente para su caso, pero debería ser la misma en todos los dominios / subdominios. No siempre es cierto por defecto.

Andrii Nemchenko
fuente
1

Usa esto, funciona:

ini_set('session.cookie_domain', 
    substr($_SERVER['SERVER_NAME'],strpos($_SERVER['SERVER_NAME'],"."),100));
Iván
fuente
parece que está configurando la cookie para el tld ... ¿o me falta algo?
chacham15
1

Uso combinado de sesiones de cookies de subdominio y dominio raíz

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

He probado trabajos

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

example.com/sessionview.php // 123

- códigos

<?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); 
?>
Isa ilimitada
fuente
0

Tengo la idea de que no quieres algo como OpenID, como sugiere Joel, pero quieres tener acceso a los datos de la sesión en varios dominios.

La única posibilidad en la que puedo pensar como solución para ese problema es almacenar los datos de sesión en una base de datos y sacarlos de esa base de datos.

Thomas
fuente
Bien, aunque la autenticación es parte de lo que quiero hacer, también me interesan los datos de la sesión que se almacenan mientras el usuario está trabajando.
dragonmantank
0

No puedo hablar por otras versiones de PHP, pero en 5.6.6, simplemente establecer el session.cookie_domainvalor en el php.iniarchivo hizo el truco para permitir que todos mis subdominios en iPage compartieran el mismo conjunto de variables de sesión.

Asegúrese de eliminar cualquier cookie existente relacionada con su dominio de su navegador para probar.

session.cookie_domain = '.yourdomainname.example'

Oh, no sé si hay alguna diferencia, pero también estoy usando el inicio automático de sesión.

session.auto_start = 1
user3232196
fuente
0

Simplemente intente usar el siguiente código justo encima del session_start()método

$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);
mohsin.mr
fuente
0

He leído todas las respuestas anteriores, creo que mi respuesta es útil para las personas que buscan en Google esto:

  • asegúrese de que los navegadores envíen la cookie de sesión a los servidores (de dominio y subdominios), configure el dominio de la cookie de sesión como .example.com.

  • Asegúrese de que PHP encuentre el "objetivo" correcto para restaurar la variable de sesión:

    • Si el dominio y los subdominios apuntan a la misma máquina (tal vez diferentes hosts virtuales), asegúrese de que session_save_pathsea ​​el mismo para todos (lo probé)
    • Si el dominio y los subdominios apuntan a máquinas diferentes, el almacenamiento común (como la base de datos) es mejor para guardar y restaurar los datos de la sesión (aún no lo probé). Utilice session_set_save_handlerpara hacer eso.
user953985
fuente
0

Sé que esto es antiguo, pero funciona bien para mí con varios dominios y subdominios en la misma caja.

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

}

?>

Ian
fuente
6
¿Qué pregunta estás respondiendo? ¿Y cómo mejora esto en las otras 9 respuestas?
random_user_name
0

Utilizar :

session_name("put_a_session_name");
session_start([
  "cookie_domain" => ".example.com",
  "cookie_path" => "/"
]);
Shakil Ahmmed
fuente
-2

Una solución rápida y sucia es usar esto para su redirección:

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

esto agregará algo similar ?PHPSESSID=etnm7kbuf5lg0r6tv7je6ehtn4a la URL, que le dice a PHP la identificación de sesión que debe usar.

sakabako
fuente
3
También lo deja muy vulnerable al robo de sesión :) El problema no es que los ID de sesión no coincidan (lo son, vea mi publicación actualizada), sino que los datos no se mueven entre los dominios.
dragonmantank
De acuerdo, esto es muy vulnerable dejando el ID de sesión en la cadena de consulta.
Ian Jamieson
4
Las cookies también se envían como texto sin formato, esto no abre ninguna vía que no estuviera ya abierta. No digo que sea una buena solución, pero no es menos seguro que usar cookies.
sakabako
1
Es menos seguro en el sentido de que los usuarios pueden ser (engañados) para compartir su URL y, por lo tanto, compartir su ID de sesión activa. Es mucho menos probable que un usuario comparta su cookie de identificación de sesión sin saberlo.
Bastiaan ten Klooster