3 декабря 2013 г.

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

Причина всем известна, на сервере через определенный момент времени при отсутствии к нему обращений истекает сессия. Что же делать? Можно увеличить время её жизни, изменив значение параметра session.gc_maxlifetime в php.ini или задав его в файле .htaccess через директиву php_value. Но не на каждом хостинге это возможно, к тому же с точки зрения безопасности это неправильно, поскольку время жизни сессии направлено не только на защиту от переполнения файловой системы, но и на забывчивого пользователя, который может оставить компьютер с авторизованной панелью администрирования.

Можно периодически обращаться к серверу в фоновом режиме по технологии Ajax, используя следующую конструкцию в файле ./admin/view/template/common/header.tpl:

<script type="text/javascript">
$(document).ready(function() {
setInterval(function() {$.ajax({ url: location.href });
}, 20000);
});
</script>

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

1. В конце файла ./admin/index.php перед строкой $response->output(); добавьте следующий код:

if (isset($session->data['user_id'])) {
setcookie('session_status', true, time() + ini_get('session.gc_maxlifetime') - 5);
} elseif (isset($_COOKIE['session_status']))  {
setcookie('session_status', false);
}

2. В соответствующих языку файлах ./admin/language/russian/common/header.php и ./admin/language/english/common/header.php добавьте перевод:
$_['text_session_expire'] = 'Ваша сессия истекла! Если Вы не сохранили данные, то при следующем запросе они могут быть утеряны!';
$_['text_session_expire']  = 'Your session has expired! If you haven\'t saved data, they will be lost at next request!';

3. В файле ./admin/controller/common/header.php найдите строку $this->data['stores'] = array(); и перед ней добавьте следующие строки:

$this->data['text_session_expire'] = $this->language->get('text_session_expire');
$this->data['token'] = $this->session->data['token'];

4. В файле-шаблоне ./admin/view/template/common/header.tpl до строки $(document).ready(function(){ добавьте <?php if ($logged) { ?>var sessionControl = {is_typed: false, intervalId: 0};<?php } ?>
после неё:

<?php if ($logged) { ?>
sessionControl.intervalId = setInterval(function(){
if($.cookie('session_status') === null) {
if (sessionControl.is_typed) {
$.get('?route=tool/error_log&token=<?php echo $token; ?>');
sessionControl.is_typed = false;
} else {
clearInterval(sessionControl.intervalId);
alert('<?php echo $text_session_expire; ?>');
}

}, 2500);

$(document).keypress(function(e) {
sessionControl.is_typed = true;
});
<?php } ?>

Приведенное выше решение с интервалом в 2,5 секунды будет опрашивать наличие cookie
session_status. Если данный cookie будет аннулирован браузером, то значит время сессии фактически истекло и об этом пользователь будет уведомлен. Если в период действия cookie будет нажата клавиша (процесс набора текста), то к моменту анулирования cookie будет выполнено фоновое обращение к серверу с целью продления жизни сессии. Обратите внимание, что в первом пункте срок существования cookie сокращён на 5 секунд, которого достаточно для покрытия интервала функции setInterval и отправки асинхронного запроса (при необходимости разницу можно увеличить).

Для тех, кто не готов тратить собственное время на реализацию данного решения, то возможна помощь со стороны автора

3 комментария:

  1. Цитата:
    "1. В конце файла ./admin/index.php перед строкой $response->output(); добавьте следующий код:

    if (isset($session->data['user_id'])) {
    setcookie('session_status', true, time() + ini_get('session.gc_maxlifetime') - 5);
    } elseif (isset($_COOKIE['session_status'])) {
    setcookie('session_status', false);
    }"

    Что означает цифра 5 в MaxLifeTime?

    ОтветитьУдалить
    Ответы
    1. Об этом ведь в статье сказано. Это небольшой запас по времени, чтобы сессия не была закрыта до того, как будет выполнен фоновый запрос.

      Удалить
    2. Зачем читать если можно спросить) О времена..

      Удалить

  • RSS
  • Twitter
  • Youtube