session_regenerate_id и обработчик базы данных - PullRequest
3 голосов
/ 27 декабря 2010

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

Когда пользователь входит в систему с именем пользователя / паролем, я делаю session_regenerate_id и после этого я пытаюсь выбрать текущийsession_id.

Вот мой код

session_regenerate_id();
echo $checkQ=" SELECT * FROM my_sessions WHERE id='".session_id()."'  ";
......

, но я не получаю никаких результатов.Идентификатор сессии - правильный.

После окончания загрузки страницы и копирования вставьте команду SQL в phpMyAdmin, я получу результаты.

Я знаю, что это глупо, но единственная причина, о которой я могу думатьявляется то, что session_regenerate_id () "слишком медленно", поэтому, когда я пытаюсь прочитать session_id на следующей строке, session_id еще не создан в базе данных.

Может кто-нибудь помочь мне!

Ответы [ 2 ]

2 голосов
/ 24 февраля 2011

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

Вызов session_generate_id() приведет к изменению значения session_id():

<?php
$before = session_id();
session_regenerate_id();
$after = session_id();
var_dump($before == $after); // outputs false

Эта проблема проявилась у меня, потому что в обработчике записи сеанса я делал это (конечно, без таких поддельных имен методов):

<?php
class MySQLHandler
{
    function read($id)
    {
        $row = $this->doSelectSql($id);
        if ($row) {
            $this->foundSessionDuringRead = true;
        }
        // snip
    }

     function write($id, $data)
     {
         if ($this->foundSessionDuringRead) {
             $this->doUpdateSql($id, $data);
         }
         else {
             $this->doInsertSql($id, $data);
         }
     }
}

Метод write () работал нормально, если session_regenerate_id() никогда не вызывался. Однако, если он был вызван, аргумент $ id для write() отличается от $ id, переданного в read(), поэтому обновление не найдет никаких записей с новым $ id, потому что они никогда не были вставлены.

Некоторые люди предлагают использовать синтаксис MySQL «REPLACE INTO», но он удаляет и заменяет строку, которая приводит к хаосу, если вы хотите иметь столбец с датой создания. Что я сделал, чтобы исправить проблему, так это удержать идентификатор сеанса, который был передан read, а затем обновить идентификатор сеанса в базе данных во время записи, используя идентификатор, переданный read в качестве ключа:

<?php
class MySQLHandler
{
    function read($id)
    {
        $row = $this->doSelectSql($id);
        if ($row) {
            $this->rowSessionId = $id;
        }
        // snip
    }

    function write($id, $data)
    {
        if ($this->rowSessionId) {
            $stmt = $this->pdo->prepare("UPDATE session SET session_id=:id, data=:data WHERE session_id=:rowSessionId AND session_name=:sessionName");
            $stmt->bindValue(':id', $id);
            $stmt->bindValue(':rowSessionId', $this->rowSessionId);
            $stmt->bindValue(':data', $data);
            $stmt->bindValue(':sessionName', $this->sessionName);
            $stmt->execute();
        }
        else {
            $this->doInsertSql($id, $data);
        }
    }
}
1 голос
/ 28 мая 2013

Я думаю, у меня та же проблема, что и у вас. Мне неясно, является ли это функцией PHP (кеша) или ошибкой.

Проблема в том, что при использовании пользовательского SessionHandler и вызове session_regenerate_id (true) новый сеанс не создается до тех пор, пока сценарий не завершится. Я подтвердил это, выполнив то же самое, что и вы: ВЫБОР нового идентификатора сеанса из базы данных. И нового сеанса там нет. Однако после завершения сценария это так.

Вот как я это исправил:

$old_id = session_id();
// If you SELECT your DB and search for $old_id, it will be there.

session_regenerate_id(TRUE);

$new_id = session_id();
// If you SELECT your DB for either $old_id or $new_id, none will be there.

session_write_close();
session_start();

// If you SELECT your DB for $new_id, it will be there.

Поэтому решение (обходной путь), к которому я пришел, состояло в том, чтобы заставить PHP написать сессию. Надеюсь, это поможет.

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