Сессии PHP в поддоменах 2 - PullRequest
3 голосов
/ 08 марта 2012

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

Так что мне нужно иметь сеансы в поддоменах (www.example.com до 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 ничего не выводит.
Как сделать forum.example.com вывод 123?

Я пытался session.cookie_domain = .example.com, но ничего не изменилось

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

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

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

Спасибо

Ответы [ 2 ]

2 голосов
/ 13 марта 2012

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

Перво-наперво: поскольку вы получаете такой же идентификатор сеанса от оба сервера, мы можем исключить любые проблемы, связанные с cookie.Очевидно, что вы успешно создаете файл cookie с именем a_name (хотя я бы рекомендовал только буквенно-цифровые символы для этого имени файла cookie ) в www.example.com и успешно читали этот файл a_name в 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 работают как ТО ЖЕ ПОЛЬЗОВАТЕЛЬ И ГРУППА .Это очень важно!Для 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_* снова, чтобы увидеть изменение пользователя и / или группы.

1 голос
/ 13 марта 2012

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

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

Для моего примера я буду использовать базу данных, поскольку эту идею я передаю, а не базу данных/ методы доступа к файлу, у меня будут удалены ненужные строки, IE: Как подключиться к базе данных.Если вам нужна эта концепция или кто-то еще хочет, чтобы я заполнил пробелы для полноты, просто оставьте комментарий.На с кодом.Я бы выбрал совершенно другой подход.Исходя из того, что я понял из вашего вопроса и связанного с ним поста, вы пытаетесь поделиться сеансом, используя общее имя сеанса.

  1. Каждый сайт имеет свой собственный идентификатор сеанса.
  2. Каждый сайт имеет свой собственный файл cookie аутентификации ($ _COOKIE ['userid'] или $ _COOKIE ['userhash']).
  3. Создаются отдельные сеансы, и на каждом сайте сохраняется общий файл cookie.
    • Используя собственный обработчик сеансов, каждый сайт считывает одни и те же данные.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 - site_name (example.com) - hash - timeout - повторно подтвердить подлинность

и изменить таблицу session_data, поэтому вместо доступа к ключу $=> пара $ val по хешу, доступ к нему осуществляется по user_id.Спасибо за чтение, надеюсь, это кому-нибудь пригодится.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...