Сеансы PHP через поддомены 2

Это дополнение к сеансам PHP в поддоменах
Я пробовал то, что указано в этом вопросе, и я вижу, что вопрос не был дан.

Поэтому мне нужно иметь сеансы по forum.example.com ( www.example.com to forum.example.com )

Что я сделал на www.example.com

 session_name("a_name"); session_set_cookie_params(0, '/', '.example.com'); session_start(); echo session_id(); $_SESSION['test'] = 123; 

На сайте forum.example.com

 session_name("a_name"); session_set_cookie_params(0, '/', '.example.com'); session_start(); echo session_id(); print_r($_SESSION); 

Session_id точно такие же, но $ _SESSION ничего не выводит.
Как сделать выход на forum.example.com 123 ?

Я попробовал session.cookie_domain = .example.com но ничего не менял

Когда я forum.example.com на forum.example.com он разрушает сеансы www.example.com , и он делает то же самое с другой стороны, например, если он обнаруживает, что он исходит из другого поддомена и стирает все для обеспечения безопасности.

2 поддомена находятся на одном сервере Debian

Еще одна вещь, которую я заметил, заключается в том, что без session_name и session_set_cookie_params он все еще имеет точно такой же session_id, когда я устанавливаю session.cookie_domain

Спасибо

Хорошо, я подумал об этом некоторое время, и я думаю, что у меня это есть.

Прежде всего: поскольку вы получаете одинаковый идентификатор сеанса с обоих серверов, мы можем исключить любые проблемы, связанные с cookie. Очевидно, что вы успешно создаете файл cookie с именем a_name (хотя я бы рекомендовал только буквенно-цифровые символы для этого имени cookie ) на www.example.com и успешно прочитал этот a_name cookie forum.example.com на forum.example.com . Но, как вы сказали, вы не получаете никаких данных с forum.example.com . session.cookie_lifetime = 0 не является проблемой: это означает, что cookie сеанса остается до закрытия браузера .

Мы должны углубиться в обработку сеансов PHP немного дальше. Идентификатор сеанса, который вы читаете с помощью session_id() относится к файлу на вашем сервере. Как правило, этот файл присутствует в /tmp/sess_$session_id . Содержимое этого файла представляет собой массив $_SESSION , сериализованный. (Имейте в виду, что данные не сериализуются так же, как это делает serialize() в PHP … но это не важно сейчас.).

Я думаю, что это проблема с правами на файл:

  1. /tmp/sess_$session_id устанавливается с пользователем и группой www.example.com .
  2. forum.example.com пытается открыть /tmp/sess_$session_id , но не имеет соответствующих разрешений .
  3. В результате вы получаете пустой результат при попытке print_r($_SESSION);

Решение :
Проверьте конфигурационный файл своего сервера, чтобы убедиться, что www.example.com и forum.example.com работают как forum.example.com ПОЛЬЗОВАТЕЛЬ И ГРУППА . Это очень важно! Для Apache найдите свой файл * .conf:

 User youruser Group yourgroup 

Для nginx найдите nginx.conf:

 user youruser yourgroup; 

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

Вы можете убедиться, что это проблема, сначала загрузив www.example.com а затем sudo ls -ltc sess_* в оболочку вашего сервера через SSH (найдите sess_ завершающийся в $session_id ). Затем загрузите forum.example.com а затем sudo ls -ltc sess_* снова, чтобы увидеть изменение пользователя и / или группы.

Для этого ответа я сделал несколько предположений:

  • Пользователь должен вводить там учетные данные, по крайней мере, один раз в каждом домене (любой другой способ был бы серьезной проблемой безопасности)
  • У вас есть доступ к базе данных или файловому пространству за пределами веб-корня.
  • субдомен, домен или любое другое имя будут называться «сайтом»,
  • Цель состоит в том, чтобы иметь доступный общий файл (физический файл или сериализованный в базе данных) с каждого сайта / домена.

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

Если эта концепция является тем, чем вы были, или если кто-то еще хочет, чтобы я заполнил пробелы для полноты, просто оставьте комментарий. С кодом.

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

  1. Каждый сайт имеет свой собственный идентификатор сеанса.
  2. На каждом сайте есть собственный файл cookie для проверки подлинности ($ _COOKIE ['userid'] или $ _COOKIE ['userhash']).
  3. Создаются отдельные сеансы, и общий куки-файл хранится на каждом сайте.
    • Используя собственный обработчик сеанса, каждый сайт считывает одни и те же данные. class MySessionHandler implements SessionHandlerInterface
    • Моя мысль была еще более простым, класс, который действует как обработчик сеанса, чтение / запись в общий файл. Поскольку обработчик сеанса php не сохраняет данные до завершения сценария.

Оригинальная идея – не вдаваться в подробности, это просто для справки.

 class MySessionHandler implements SessionHandlerInterface { private $savePath; public function read($id) { $id = some_user_authentication_function(); $hash = $_COOKIE['_h']; $result = mysql_query("SELECT sess_data FROM login_table WHERE user_id = {$id} AND hash = {$hash}"); return $result['sess_data']; } public function write($id, $data) { $id = some_user_authentication_function(); $hash = $_COOKIE['_h']; $result = mysql_query("UPDATE login_table SET sess_data = {$data} WHERE user_id = {$id} AND hash = {$hash}"); return ($result === false) ? false : true; } } $handler = new MySessionHandler(); session_set_save_handler($handler, true); session_start(); 

 class customSessionHandler { private $hash; private $id; private $sess_db; public function __construct($db) { $this->hash = $_COOKIE['hash']; $this->id = some_user_authentication_function($this->hash); $this->sess_db = $db; } public function get($key) { $query = "SELECT value ". "FROM ".$this->sess_db. "WHERE user_id = {$id} ". " AND hash = {$hash} ". " AND key = {$key}"; $result = mysql_query($query); return $result['key']; } public function set($key, $val) { $query = "REPLACE INTO ".$this->sess_db. "SET {$key} = {$val} ". "WHERE user_id = {$id} ". " AND hash = {$hash}"; return (mysql_query($query) === false) ? false : true; } } $handler = new customSessionHandler('sess_data'); session_start(); 

Как было указано в начале, любой код, который не является существенным для объяснения концепции, был удален.
Вещи, которые могут быть не очевидны для всех: – $ key и $ val необходимо дезинфицировать перед отправкой в ​​базу данных. (предотвращение инъекций). Хеш отправляется в ваши функции входа, поэтому хэш может использоваться для очистки данных сеанса, когда это необходимо, также может использоваться при аутентификации пользователя. – Готовые заявления mysql были бы идеальными здесь, поэтому вы можете подготовить два запроса в конструкторе, а затем просто повторно использовать инструкцию для каждого вызова. Затем поместите код закрытия соединения в деструктор.

После мысли

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

Для реализации этого было бы так же просто, как настроить еще одну таблицу, содержащую: – user_id – имя_сайта (example.com) – hash – timeout – повторная аутентификация

и изменение таблицы session_data, поэтому вместо доступа к парам $ key => $ val хэшем вы получаете доступ к нему user_id.

Спасибо за чтение, надеюсь, это будет полезно кому-то.