Сеансы PHP через поддомен
Я пытаюсь настроить следующее:
auth.domain.com
sub1.domain.com
sub2.domain.com
где, если пользователь посещает sub1.domain.com или sub2.domain.com, и они не вошли в систему, они перенаправляются на auth.domain.com и могут войти в систему. sub1.domain.com и sub2.domain.com два отдельных приложения, но используют одинаковые учетные данные.
Я попытался установить следующее в моем php.ini:
session.cookie_domain = ".domain.com"
но, похоже, информация не передается из одного домена в другой.
[Редактировать]
Я попробовал следующее:
sub1.domain.com/test.php
session_set_cookie_params(0, '/', '.domain.com');
session_start();
print session_id() . "<br>";
$_SESSION['Regsitered'] = 1;
echo '<a href="http://auth.domain.com/test.php">Change Sites</a>'
auth.domain.com/test.php
session_set_cookie_params(0, '/', '.domain.com');
session_start();
print session_id() . "<br>";
$_SESSION['Checked'] = 1;
print_r($_SESSION);
Идентификаторы сеанса в точности совпадают, но когда я выкидываю переменную $_SESSION, она не показывает оба ключа, а только тот ключ, который я установил в каждом домене.
[Редактировать 2]
Я обновил [Изменить]
16 ответов
Я не знаю, существует ли проблема до сих пор, но я столкнулся с той же самой проблемой и решил ее, установив имя сеанса перед вызовом session_set_cookie_params():
$some_name = session_name("some_name");
session_set_cookie_params(0, '/', '.some_domain.com');
session_start();
Я ничего не изменил в моем php.ini, но теперь все работает нормально.
Одна вещь, которая может таинственным образом предотвратить чтение данных сеанса на поддомене, несмотря на то, что файлы cookie правильно установлены на .domain.com
это патч PHP Suhosin. Вы можете настроить все правильно, согласно примерам в вопросе, и это может просто не работать.
Отключите следующие настройки сеанса Suhosin, и вы снова в деле:
suhosin.session.cryptua = Off
suhosin.session.cryptdocroot = Off
Попробуйте использовать:
session.cookie_domain = "domain.com"
Вместо:
session.cookie_domain = ".domain.com"
Обратите внимание на пропущенный период.
Будьте осторожны при использовании этого, потому что это поддерживается не всеми браузерами.
Была именно эта проблема - я хотел, чтобы значения сеанса, созданные в x.example.local, были доступны на example.local и наоборот.
Все найденные решения говорят об изменении домена Session с помощью 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_domain. Сервер восстановит старый сеанс, и поэтому вы получите ложноотрицательные результаты. (во многих сообщениях упоминается использование session_name('stuff') для точно такого же эффекта)
Я решил это так
ini_set('session.cookie_domain', '.testdomain.dev');
session_start();
Потому что я работал на localhost
ini_set('session.cookie_domain', '.localhost');
не работал, он видит.localhost в качестве верхнего уровня вместо.com/.local/... (я подозреваю)
Я также использовал.dev, потому что работа над OS X, похоже, не разрешает.com как первый в HOSTS
Я подтвердил. Joreon ответ правильный. Я не могу комментировать, потому что моей репутации недостаточно, поэтому я публикую свой комментарий здесь.
Определите константу в файле конфигурации. Если вы хотите изменить его, нет необходимости изменять целые файлы.
define('ROOT_DOMAIN', 'mysite.com');
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();
}
else {
if (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
Используйте его на каждом домене / поддомене:
session_name('name');
ini_set('session.cookie_domain', '.example.com');
ini_set('session.save_path', '/var/lib/php/session');
session_start();
Путь для session.save_path
может отличаться для вашего случая, но оно должно быть одинаковым для каждого домена / субдомена. Это не всегда верно по умолчанию.
Используйте это, это работает:
ini_set('session.cookie_domain',
substr($_SERVER['SERVER_NAME'],strpos($_SERVER['SERVER_NAME'],"."),100));
Субдомен и корневой домен сессий cookie с комбинированным использованием
Ресурс: http://php.net//manual/tr/function.session-set-cookie-params.php
Я проверял работы
sub.exampledomain.com/sessionadd.php?id=123
exampledomain.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);
?>
Я не могу говорить о других версиях PHP, но в 5.6.6 просто установить session.cookie_domain
значение в php.ini
file сделал свое дело, чтобы позволить всем моим поддоменам на iPage использовать один и тот же набор переменных сеанса.
Обязательно удалите из браузера все существующие файлы cookie, связанные с вашим доменом, для тестирования.
session.cookie_domain = '.yourdomainname.org'
О, не знаю, имеет ли это какое-то значение, но я также использую автозапуск сеанса.
session.auto_start = 1
Я понял, что вам не нужно что-то вроде OpenID, как предлагает Джоэл, но вы хотите иметь доступ к данным сеанса в нескольких доменах.
Единственная возможность, которую я могу рассматривать как решение этой проблемы, - это сохранить данные сеанса в базе данных и извлечь их из этой базы данных.
Использование:
session_name("put_a_session_name");
session_start([
"cookie_domain" => ".example.com",
"cookie_path" => "/"
]);
У меня была похожая проблема, однако, это решение было хорошо для меня, возможно, поможет другим в будущем
редактировать php.ini
session.cookie_domain = ".example.com"
магия здесь
suhosin.session.cryptdocroot = Off
suhosin.cookie.cryptdocroot = Off
Просто попробуйте использовать следующий код чуть выше session_start()
метод
$sess_life_time = 21600; //in seconds
$sess_path = "/";
$sess_domain = ".you-site-name.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);
Я прочитал все ответы выше, я думаю, что мой ответ полезен для людей, гуглящих это.
* Убедитесь, что браузеры отправляют сессионные куки-файлы обратно на серверы (домена и поддоменов), установите домен сессионных куки-файлов как ".example.com".
* Убедитесь, что php находит правильную "цель" для восстановления сеанса var. Если домен и дочерние домены указывают на одну и ту же машину (возможно, разные виртуальные хосты), убедитесь, что "session_save_path" одинаков для всех (я проверял) - Если домен и поддоменов указывают на разные машины, общее хранилище (например, база данных) лучше всего подходит для сохранения и восстановления данных сеанса (я еще не тестировал). Используйте "session_set_save_handler", чтобы сделать это.
Я знаю, что это старый, но он отлично работает для меня с несколькими доменами и поддоменами в одном окне.
<?php
define('site_domain','domain.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);
}
?>
Быстрое и грязное решение состоит в том, чтобы использовать это для вашего перенаправления:
header( $url.'?'.session_name().'='.session_id() );
это добавит что-то вроде?PHPSESSID=etnm7kbuf5lg0r6tv7je6ehtn4 к URL, что сообщает PHP идентификатор сеанса, который он должен использовать.