Сеансы PHP в поддоменах

Я пытаюсь настроить следующее:

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

Если пользователь посещает sub1.example.com или sub2.example.com и не вошел в систему, он перенаправляется на auth.example.com и может войти в систему.

sub1.example.com и sub2.example.com - два разных приложения, но используют одни и те же учетные данные.

Я попытался установить в своем php.ini следующее:

session.cookie_domain = ".example.com"

но похоже, что он не передает информацию из одного домена в другой.

[Изменить]

Я пробовал следующее:

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

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


person dragonmantank    schedule 30.06.2009    source источник
comment
Вы также должны включить его в своем коде, см. http://us2.php.net/manual/en/function.session-set-cookie-params.php   -  person Residuum    schedule 30.06.2009
comment
У меня почти такая же настройка (я установил домен cookie сеанса с помощью вызова session_set_cookie_params), и он отлично работает.   -  person Milen A. Radev    schedule 30.06.2009
comment
Вот хорошая функция, которая работает stackoverflow.com / questions / 2835486 /   -  person boksiora    schedule 14.07.2013


Ответы (17)


Я не знаю, существует ли проблема, но я просто столкнулся с той же проблемой и решил ее, установив имя сеанса перед вызовом session_set_cookie_params():

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

Я ничего не менял в своем php.ini, но теперь все работает нормально.

person jeroen    schedule 22.09.2009
comment
Подтверждаю, это решает проблему. Я устал получать там свой ответ: stackoverflow.com/questions/4948340/. Но я нашел это здесь. - person Roman; 10.02.2011
comment
Отлично работает! Давно искал это. Это сделал $some_name = session_name("some_name");. Спасибо и проголосовали за. - person Kit; 17.03.2011
comment
Добавление session_name("domain"); также было для меня недостающим ингредиентом. Документация на php.net относительно этих настроек сеанса отсутствует. На php.net есть сообщения сообщества, в которых указано, что необходимо определить session.name, прежде чем можно будет применить изменения в session_set_cookie_params (). - person David Carroll; 03.07.2011
comment
Ага. подтвержденный. славный там целую вечность ходил кругами;) - person Daithí; 16.01.2012
comment
ПРИМЕЧАНИЕ ... мне пришлось закрыть браузер и перезапустить его, чтобы он заработал на жизненном сервере. Оставьте любую ini_set("session.cookie_domain", ".domain.com"); причину, по которой он создавал новый идентификатор сеанса при каждом обновлении. - person Daithí; 16.01.2012
comment
session_name () мне не понадобилось в случае, когда cookie_domain был установлен на .domain.com с самого начала (использования веб-сайта). Насколько я понимаю, он решает проблему с тем, что у пользователя уже есть файл cookie PHPSESSID (стандартное имя сеанса), хранящийся для поддоменов, поэтому даже если я прихожу с другого поддомена с новым файлом cookie .domain.com, мой уже Вместо этого используется сохраненный файл cookie sub.domain.com. Установка другого имени сеанса отменяет эти старые файлы cookie. - person Jānis Elmeris; 10.07.2013
comment
Обратите внимание, что домен должен содержать хотя бы одну точку. Например, session_set_cookie_params(0, '/', '.local'); не работает, а session_set_cookie_params(0, '/', '.domain.local'); работает. - person Olav; 11.08.2013
comment
+1 Сработал прямо из коробки и решил мою проблему, когда пользователь вошел в систему, а затем сменил язык (который использует поддомены, например fr.mysite.com, de.mysite.com). - person imperium2335; 25.01.2014
comment
@jeroen Я также загрузил свой веб-сайт в поддомен ... его домен - www.agicent.com, но мои основные файлы находятся на ... ibuildmart.agicent.com/cms. Не могли бы, пожалуйста, помочь мне. Здесь сессия не работает. Я занимаюсь этой проблемой уже много дней. - person Abhishek; 29.05.2014
comment
Это сработало и у меня, и я решил проблему, чувствуя чудо. - person Homnath Bagale; 23.04.2015
comment
Это помогло мне разобраться с другой проблемой. Массив сеанса был очищен между страницами, так что это фактически заставило их переменные оставаться там, где они должны были быть. Спасибо за ваши усилия. Настоящая спасательница! - person MDChaara; 17.01.2016
comment
примечание: у меня возникла проблема с использованием. символ в session_name. Ошибок не было, но сеанс каждый раз был пустым, поэтому попробуйте изменить имя сеанса, если оно не работает :) - person Buksy; 29.03.2016

Одна вещь, которая может загадочным образом предотвратить чтение данных сеанса на поддомене, несмотря на то, что файлы cookie правильно установлены на .example.com, - это патч PHP Suhosin. Вы можете настроить все правильно, как показано в примерах в вопросе, и это может просто не работать.

Отключите следующие настройки сеанса Suhosin, и вы снова в деле:

suhosin.session.cryptua = Off 
suhosin.session.cryptdocroot = Off
person drewm    schedule 25.06.2011

Попробуйте использовать:

session.cookie_domain = "example.com"

Вместо:

session.cookie_domain = ".example.com"

Обратите внимание на пропущенный период в начале.

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

person George Claghorn    schedule 30.06.2009
comment
Какие браузеры не поддерживаются? - person gawpertron; 16.02.2011
comment
какая поддержка браузера должна быть здесь? это действие на стороне сервера. - person Kuf; 20.10.2014

Была эта точная проблема - я хотел, чтобы значения сеанса, созданные в x.example.local, были доступны в example.local и наоборот.

Во всех найденных мною решениях говорится об изменении домена сеанса с помощью php_value session.cookie_domain .example.local в .htaccess (или через php.ini или через ini_set).

Уловка заключалась в том, что я устанавливал session.cookie_domain для всех поддоменов (пока нормально), но также и для основного домена. Очевидно, что установка session.cookie_domain в основном домене - это недопустимо.

В основном, как это сработало для меня:

  • установите session.cookie_domain для ВСЕХ ПОДдоменов.
  • не устанавливайте его для основного ДОМЕНА

О да, пожалуйста, убедитесь, что у домена есть TLD (в моем случае .local). Протокол Http не позволяет хранить файлы cookie / сеансы в домене без .tld (то есть localhost не будет работать, но stuff.localhost будет).

РЕДАКТИРОВАТЬ. Также убедитесь, что вы всегда очищаете файлы cookie своего браузера во время тестирования / отладки сеансов на поддоменах. Если вы этого не сделаете, ваш браузер всегда будет отправлять старый файл cookie сеанса, для которого, вероятно, еще не установлен правильный cookie_domain. Сервер восстановит старую сессию, поэтому вы получите ложноотрицательные результаты. (во многих сообщениях упоминается использование session_name ('stuff') для того же эффекта)

person Valentin Florea    schedule 03.12.2013

Я решил это вот так

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

Потому что я работал на localhost

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

не работает, он видит .localhost как верхний уровень вместо .com / .local / ... (я подозреваю)

person xtds    schedule 12.04.2012
comment
Также исправил это для моей машины - Ubuntu 14.04 - person dennis; 01.02.2015

Я подтвердил. joreon ответ правильный. Я не могу комментировать, потому что моей репутации недостаточно, поэтому я размещаю свой комментарий здесь.

Определите константу в файле конфигурации. Если вы хотите его изменить, не нужно изменять файлы целиком.

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

Имя сеанса не может состоять только из цифр, должна присутствовать хотя бы одна буква. В противном случае каждый раз создается новый идентификатор сеанса.

Используйте следующий код, чтобы начать использовать сеанс

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

Я использую эту функцию:

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
person Terry Lin    schedule 12.05.2015

Используйте его на каждом домене / субдомене:

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

Путь для session.save_path в вашем случае может быть другим, но он должен быть одинаковым для каждого домена / субдомена. По умолчанию это не всегда так.

person tellnobody    schedule 17.11.2013

Используйте это, это работает:

ini_set('session.cookie_domain', 
    substr($_SERVER['SERVER_NAME'],strpos($_SERVER['SERVER_NAME'],"."),100));
person Ivan    schedule 05.10.2010
comment
похоже, что он устанавливает cookie для tld ... или я что-то упускаю? - person chacham15; 21.01.2015

Совместное использование сеансов cookie субдомена и корневого домена

Ресурс: http://php.net//manual/tr/function.session-set-cookie-params.php

Я тестировал работы

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

example.com/sessionview.php // 123

- коды

<?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); 
?>
person Limitless isa    schedule 28.08.2014

Я понимаю, что вам не нужно что-то вроде OpenID, как предлагает Джоэл, но вы хотите иметь доступ к данным сеанса в нескольких доменах.

Единственная возможность, которую я могу рассматривать как решение этой проблемы, - это сохранить данные сеанса в базе данных и вытащить их из этой базы данных.

person Thomas    schedule 30.06.2009
comment
Правильно, хотя аутентификация - это часть того, что я хочу сделать, меня также интересуют данные сеанса, которые сохраняются во время работы пользователя. - person dragonmantank; 30.06.2009

У меня была аналогичная проблема, однако это решение было для меня хорошим, возможно, поможет другим в будущем

отредактируйте php.ini

session.cookie_domain = ".example.com"

магия здесь

suhosin.session.cryptdocroot = Off

suhosin.cookie.cryptdocroot = Off

https://www.sitepoint.com/community/t/sessions-across-subdomains-domain-com-phpsessid-changes/3013/19.

person Willian Santana    schedule 26.07.2016

Я не могу говорить о других версиях PHP, но в 5.6.6 простая установка значения session.cookie_domain в файле php.ini позволила всем моим поддоменам на iPage использовать один и тот же набор переменных сеанса.

Обязательно удалите из браузера все существующие файлы cookie, относящиеся к вашему домену, для проверки.

session.cookie_domain = '.yourdomainname.example'

О, не знаю, имеет ли это значение, но я также использую автозапуск сеанса.

session.auto_start = 1
person user3232196    schedule 03.11.2016

Просто попробуйте использовать следующий код чуть выше session_start() метода

$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);
person mohsin.mr    schedule 09.07.2014

Я прочитал все ответы выше, я думаю, что мой ответ будет полезен для людей, которые ищут это в Google:

  • убедитесь, что браузеры отправляют cookie сеанса обратно на серверы (домена и поддоменов), установите домен cookie сеанса как .example.com.

  • Убедитесь, что PHP нашел правильную «цель» для восстановления переменной сеанса:

    • If domain and subdomains point to the same machine (maybe different virtual hosts), make sure session_save_path is the same for all (I tested)
    • Если домен и поддомены указывают на разные машины, общее хранилище (например, база данных) лучше всего подходит для сохранения и восстановления данных сеанса (я еще не тестировал). Для этого используйте session_set_save_handler.
person user953985    schedule 21.12.2012

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

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

}

?>

person Ian    schedule 17.01.2012
comment
На какой вопрос вы отвечаете? И как это улучшает / улучшает 9 других ответов? - person random_user_name; 29.10.2012

Использовать :

session_name("put_a_session_name");
session_start([
  "cookie_domain" => ".example.com",
  "cookie_path" => "/"
]);
person Shakil Ahmmed    schedule 13.04.2020

Быстрое и грязное решение - использовать это для перенаправления:

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

это добавит что-то вроде ?PHPSESSID=etnm7kbuf5lg0r6tv7je6ehtn4 к URL-адресу, который сообщает PHP идентификатор сеанса, который он должен использовать.

person sakabako    schedule 30.06.2009
comment
Это также делает его очень уязвимым для кражи сеанса :) Проблема не в том, что идентификаторы сеанса не совпадают (они есть, см. Мой обновленный пост), а в том, что данные не перемещаются между доменами. - person dragonmantank; 30.06.2009
comment
Согласен, это очень уязвимо, оставляя идентификатор сеанса в строке запроса. - person Ian Jamieson; 18.02.2013
comment
Файлы cookie также отправляются в виде обычного текста, это не открывает никаких возможностей, которые еще не были открыты. Я не говорю, что это хорошее решение, но оно не менее безопасно, чем использование файлов cookie. - person sakabako; 01.03.2013
comment
Это менее безопасно в том смысле, что пользователи могут (обманом) поделиться своим URL-адресом и, таким образом, поделиться своим активным идентификатором сеанса. Гораздо менее вероятно, что пользователь непреднамеренно поделится своим файлом cookie с идентификатором сеанса. - person Bastiaan ten Klooster; 09.10.2017