Сессия кросс-субдомена PHP для субдомена на другом сервере

У меня есть 3 домена:

  1. member.example.com для входа в централизатор на SERVER1
  2. news.example.com для новостей на SERVER1
  3. video.example.com для видео на другом сервере SERVER2

Для кросс-поддоменных сеансов я использую:

session_name('example');
session_set_cookie_params(0, '/', '.example.com');
session_start();

Когда пользователь входит на member.example.com, все данные сеанса доступны на news.example.com, но не на video.example.com, поскольку он находится на другом сервере. Идентификатор сеанса одинаков для всех поддоменов, но, поскольку это другой физический ящик, файла сеанса там нет.

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

Я знаю подход к хранению данных в базе данных, но хочу этого избежать. Я также знаю, что могу отправлять зашифрованную информацию о сеансе в URL-адресе для video.example.com, но я чувствую, что это некрасиво, и я хочу создать чистое решение.

После обхода файлов cookie и других реализаций я изучил следующий сценарий.

На member.example.com после успешного входа в систему я попытался создать сеанс для video.example.com, вызвав страницу создания сеанса на video.example.com с помощью cURL. Я попытался использовать следующий код (и передать соответствующие поля с помощью cURL):

session_name('example');
session_set_cookie_params(0, '/', '.example.com');
session_start();
$_SESSION['id']=$_POST['id'];
$_SESSION['name']=$_POST['name'];
print_r($_SESSION)

В ответе cURL я обнаружил, что эти переменные установлены для сеанса, но, к сожалению, для вызова cURL был создан новый идентификатор сеанса. Я попытался решить это с помощью существующего идентификатора сеанса, но это не сработало.

Я знаю и другие варианты, но меня особенно интересует этот подход.


person Asad kamran    schedule 15.12.2011    source источник
comment
Кроме того, если у вас есть определенное хранилище сеансов, сеанс PHP не может быть разделен между серверами. Я думаю, вам следует подумать об использовании базы данных или хранилища ключей для хранения данных вашего сеанса...   -  person RageZ    schedule 15.12.2011
comment
Да, я знаю, для этого межсерверного правила. Но я хочу создать его, вызвав php-скрипт на video.example.com, чтобы он мог быть доступен там.   -  person Asad kamran    schedule 15.12.2011
comment
@RageZ: можешь объяснить хранение ключей-значений   -  person Asad kamran    schedule 15.12.2011
comment
Мы столкнулись с похожими проблемами при перемещении нашего сайта с одного сервера на несколько серверов. Хотя мы перешли на аутентификацию на основе файлов cookie и memcache. Это проще и важнее, поскольку сеанс php не поддерживает межсерверную аутентификацию. Наличие хорошего ключа шифрования на вашем конце и проверка данных cookie важны, а также полезны в дальнейшем, когда вы попытаетесь перенести процесс аутентификации на https или на какой-либо другой сервер.   -  person ankur.singh    schedule 15.12.2011
comment
Это было бы довольно сложно, так как есть два разных сервера. Вы должны обновлять/создавать сессию на каждом сервере каждый раз, когда вы обновляете/создаете сессию на одном из серверов. Отправка данных сеанса между серверами была бы очень неэффективной. Вы действительно не можете использовать базу данных для хранения сеансов?   -  person piotrekkr    schedule 15.12.2011
comment
@ ankur.singh: Спасибо за ваше предложение, я пытаюсь настроить memcache по другой причине (прогресс загрузки файла). Я читал, что это небезопасно, и мы должны сами обеспечить некоторую безопасность. Не могли бы вы предоставить дополнительную помощь, чтобы я мог попробовать memcache для этой проблемы.   -  person Asad kamran    schedule 15.12.2011
comment
@piotrekkr, да, хочу избежать доступа к БД, но если нет решения, я буду использовать его как последнее доступное решение. Хотя это неэффективно, небезопасно, но вы можете помочь, почему переменная сеанса не может быть установлена ​​путем вызова с сервера 1 на php-скрипт на SERVER2.   -  person Asad kamran    schedule 15.12.2011
comment
@Asadkamran В memcache мы можем сохранять данные за заданное время, поэтому, скажем, ки, вы хотите, чтобы пользователь выходил из системы через 5 минут неактивного периода, вы можете установить значение ключа login_uuid_of _user равным 1 на 300 секунд. И при каждом действии пользователя проверяйте, установлен этот ключ или нет. Если не установлено, вы можете предположить, что кто-то пытается подделать эти данные или пользователь неактивен в течение последних 5 минут.   -  person ankur.singh    schedule 15.12.2011
comment
Проблема в том, что идентификатор сеанса не совпадает. Насколько мне известно, без реализации собственного обработчика сеанса (и даже тогда, возможно, нет) вы не можете выбрать идентификатор сеанса. Кроме того, memcached не является небезопасным по своей сути. Пока доступ к нему контролируется, он безопасен. Это все равно, что сказать, что MySQL небезопасен. Это может быть, но не обязательно.   -  person Corbin    schedule 15.12.2011
comment
Кроме того, при каждой активности пользователя вы можете обновить срок действия этого ключа. И вы получите uuid пользователя из файла cookie. Но убедитесь, что вы также используете шифрование на стороне файла cookie, например, один другой файл cookie, например auth_check=md5(uuid+salt). Это не полностью защитит ваше приложение, но будет более чем безопасным, чем любое другое известное и простое решение.   -  person ankur.singh    schedule 15.12.2011
comment
@Corbin: когда я печатаю session_id(); во всех поддоменах это то же самое, что и я (как я упоминал выше, я использую это вверху::session_name('example'); session_set_cookie_params(0, '/', '.example.com'); session_start(); : : поэтому сеанс передается во все поддомены на одном сервере, но поддомен на сервере 2 может использовать только идентификатор сеанса, а не данные сеанса.) Я проверяю с помощью метода поиска в браузере, и идентификатор сеанса одинаков для всех поддоменов.   -  person Asad kamran    schedule 15.12.2011
comment
@ankur.singh: Спасибо за помощь, я попробую использовать memcache.   -  person Asad kamran    schedule 15.12.2011


Ответы (2)


На обоих серверах идентификатор сеанса, имя сеанса, параметры cookie и другие параметры сеанса должны быть одинаковыми. Таким образом, вы должны отправить session_name(), session_id(), другие параметры сеанса и данные сеанса на видеосервер. Затем на видео вы создаете

session_name($_POST['name']);
session_set_cookie_params(0, '/', '.example.com');
session_id($_POST['id']);
session_start();
$_SESSION = array_merge($_SESSION, $_POST['session_data']);

попробуй, если получится.

person piotrekkr    schedule 15.12.2011
comment
Спасибо за помощь, я уже пробовал это, у меня жесткое имя сеанса, так как оно одинаково для всех поддоменов. Но я повторю это, как вы предлагаете. Я ПОСТАВЛЯЮ это на ВСЕ: session_name('example'); session_set_cookie_params(0, '/', '.example.com'); сеанс_старт(); $id=идентификатор_сеанса(); // насколько я вижу, он возвращает тот же идентификатор, что и на другом домене sumdomain - person Asad kamran; 15.12.2011
comment
Это устанавливает имя, а не идентификатор. Вам нужно сделать, как предлагает piotrekkr, и использовать session_id (id здесь). Обратите внимание, что это должно быть до session_start() - person Corbin; 15.12.2011
comment
@piotrekkr:Спасибо, теперь это работает, хотя я уже пробовал это, передав жестко закодированный идентификатор сеанса перед запуском сеанса, но, возможно, он был неправильным или старым, в любом случае Большое спасибо. - person Asad kamran; 17.12.2011
comment
Может ли это помочь кому-то еще. Мой сценарий заключался в реализации SESSION на удаленном сервере, я хочу создать сеанс в поддомене на удаленном сервере для этой цели: при входе в систему в поддомене MEMBER я вызываю cURL Post call на удаленный Страница сервера с идентификатором сеанса и другими значениями сеанса, и эта страница создает его по назначению. Код выглядит следующим образом: - person Asad kamran; 17.12.2011
comment
function vSess($url,$fields,$rt){ foreach($fields as $key=›$val){$field_str.= $key.'='.$val.'&';} rtrim($field_str, '&'); $ch = curl_init(); curl_setopt($ch,CURLOPT_URL,$url); curl_setopt($ch,CURLOPT_POST,count($fields)); curl_setopt($ch,CURLOPT_POSTFIELDS,$field_str); if($rt==1){ curl_setopt($ch,CURLOPT_RETURNTRANSFER,1); $результат = curl_exec($ch); curl_close ($ ч); вернуть $результат; }else{ curl_exec($ch); curl_close ($ ч); }} и вызовите его следующим образом: $f=array('sid'=›session_id(), 'id'=›$_SESSION['v1'],'user'=›$_SESSION['v2']); vSess('videos.example.com/v_sess.php',$f ,0); - person Asad kamran; 17.12.2011
comment
Извините за удаление комментариев в коде из-за ограниченного количества символов для публикации комментариев://‹?php session_name('example'); session_set_cookie_params(0, '/', '.example.com'); session_id($_POST['sid']); сеанс_старт(); $_SESSION['v1']=$_POST['v1']; $_SESSION['v2']=$_POST['v2']; ?› - person Asad kamran; 17.12.2011
comment
CURLOPT_POSTFIELDS может принимать аргумент массива, curl ускользнет и присоединится к нему при отправке запроса. Смотри мануал :) - person piotrekkr; 18.12.2011

Старый вопрос, возможно, новый/лучший ответ.

Мы используем AWS с политикой автомасштабирования, поэтому по мере увеличения нагрузки мы получаем больше экземпляров, на которых выполняется наш код.

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

PHP можно относительно легко настроить для использования memcached в качестве хранилища сеансов.

Сказав это, Memcached может быть не самым подходящим хранилищем для сессий, и, оглядываясь назад, что-то, что поддерживается диском (на ум приходит Redis), может быть лучшим решением.

person Richard A Quadling    schedule 21.08.2017