Блокировка сеанса обновления Codeigniter 3, вызывающая проблемы - PullRequest
0 голосов
/ 26 ноября 2018

Мы недавно обновили старое приложение Codeigniter с 2.1.0 до 3.1.9, и все прошло гладко.За исключением того, что новая блокировка сеанса вызывает проблемы, и я задаюсь вопросом, как правильно ее исправить.

Приложение интенсивно использует AJAX, однако большинство вызовов AJAX не записывают в сеанс и неКажется, это не сломалось.

Вот пример проблемы: есть графический интерфейс с флажками, и когда ввод изменяется (флажок установлен или снят), был сделан вызов AJAX.На другом конце этого вызова AJAX, флажки которого были отмечены, были записаны в сеанс, чтобы их запомнили от посещения к посещению.Однако, если вы отметили / сняли флажок с нескольких ящиков, вызывая выход нескольких вызовов AJAX, вы в конечном итоге выйдете из системы.Подобное поведение было обнаружено во всем приложении, где происходит запись сессий.

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

Краткосрочное решение, которое я придумала, состоит в том, чтобы отменить вызовы AJAX (который помогает, но не решает проблему самостоятельно) и отключить входы до завершения вызова AJAX.

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

1 Ответ

0 голосов
/ 27 ноября 2018

Единственным долгосрочным решением является правильное использование session_write_close().

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

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

Либо выполните ALL или NONE записей сеанса в функциях ответа AJAX.(Под «функцией ответа AJAX» я подразумеваю значение PHP controller/method URL-адреса AJAX.)

С помощью ALL вызова подхода session_write_close() в сценарии «main» перед выполнением любогоAJAX просит.Имейте в виду, что $_SESSION не зависит от session_write_close().Все элементы $_SESSION в сценарии main останутся доступными, чтобы вы могли надежно прочитать значения.Однако изменения , внесенные в $_SESSION, записываться не будут, поскольку для PHP сессия закрыта.Но это верно только для сценария, который вызывает session_write_close().

При использовании подхода NONE вам все равно может понадобиться прочитать данные сеанса.В этом случае было бы целесообразно, чтобы функции ответа AJAX вызывали session_write_close как можно скорее, чтобы минимизировать время, когда параллельные запросы блокируются.Вызов более важен для функций, которые требуют значительного времени для выполнения.Если время выполнения скрипта короткое, то явный вызов session_write_close() не нужен.Если это вообще возможно, т. Е. Нет необходимости читать данные сеанса, то отсутствие загрузки класса session может привести к более чистому коду.Это определенно исключило бы любую возможность одновременной блокировки запросов.

Не пытайтесь протестировать поведение сеанса, используя несколько вкладок в одном приложении в одном браузере.

Подумайте об использовании $config['sess_time_to_update'] = 0;, а затем явно вызовите $this->sess_regenerate((bool) config_item('sess_regenerate_destroy'));, когда и где имеет смысл изменить идентификатор сеанса, т.е. сразу после входа в систему;сразу после перенаправления на «чувствительную» страницу;и т. д.

То, что следует далее, предлагается с большим трепетом.Я проверил это с помощью драйвера «files», но не очень.Итак, покупатель остерегается.

Я обнаружил, что можно «перезапустить» сеанс, вызвав функцию PHP session_start() после использования session_write_close().CodeIgniter откроет и прочитает хранилище данных сеанса и перестроит суперглобальный $_SESSION.Теперь возможно изменить данные сеанса, и они будут записаны, когда выполнение скрипта закончится - или с другим вызовом session_write_close().

Это имеет смысл, потому что session_write_close() ничего не делает для CodeIgniter session объект.Класс все еще создается и настраивается.Пользовательский код SessionHandlerInterface CodeIgniter используется для открытия, чтения и записи данных сеанса после вызова session_start().

Возможно, эта очевидная функциональность может быть использована для решения ваших проблем.В случае, если я не был ясен ранее - используйте на свой страх и риск!

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