// 'loginUrl' => ['/site/login'],
'enableAutoLogin' => true,
],
+ 'session' => [
+ 'class' => 'yii\web\Session',
+ 'timeout' => 14400, // 4 часа — формы списаний требуют длительного заполнения
+ ],
'errorHandler' => [
'errorAction' => 'site/error',
],
return $this->render('about');
}
+ /**
+ * Продлевает PHP-сессию (keep-alive пинг от JS).
+ * Предотвращает истечение CSRF-токена при длительном заполнении форм.
+ */
+ public function actionKeepAlive()
+ {
+ Yii::$app->response->format = Response::FORMAT_JSON;
+ return ['ok' => true];
+ }
+
public function actionMenuTree()
{
// $client = new Client(['base_uri' => Yii::$app->params['API2_URL']]);
// Register Shift Reminder JavaScript
$this->registerJsFile('/js/shift-reminder.js', ['position' => \yii\web\View::POS_END]);
+// Session keep-alive: предотвращает истечение CSRF-токена при длительном заполнении форм
+$this->registerJsFile('/js/session-keep-alive.js', ['position' => \yii\web\View::POS_END]);
?>
<?php $this->beginPage() ?>
<!DOCTYPE html>
--- /dev/null
+/**
+ * Session keep-alive: периодический пинг для продления PHP-сессии.
+ * Предотвращает истечение CSRF-токена при длительном заполнении форм.
+ */
+(function () {
+ var INTERVAL_MS = 900000; // 15 минут
+ var intervalId = null;
+
+ function ping() {
+ if (window._uploadInProgress) return;
+
+ $.ajax({
+ method: 'GET',
+ url: '/site/keep-alive',
+ dataType: 'json'
+ });
+ }
+
+ function start() {
+ if (!intervalId) {
+ intervalId = setInterval(ping, INTERVAL_MS);
+ }
+ }
+
+ function stop() {
+ if (intervalId) {
+ clearInterval(intervalId);
+ intervalId = null;
+ }
+ }
+
+ // Пауза при неактивной вкладке
+ document.addEventListener('visibilitychange', function () {
+ if (document.hidden) {
+ stop();
+ } else {
+ ping();
+ start();
+ }
+ });
+
+ start();
+})();