Intereting Posts
передача строки php с несколькими строками в функцию / переменную javascript Получите средний интервал между двумя датами PHP Запрещено У вас нет разрешения на доступ к этому серверу. Сервер не может читать файл htaccess, запрещающий доступ к безопасности Как написать хорошую вставку базы данных PHP, используя ассоциативный массив wkhtmltopdf – проблема с кодировкой PHP Предупреждение: Неизвестно: произошла ошибка при закрытии оператора в Unknown в строке 0 Электронная почта PDF-приложение с PHP с использованием FPDF Google_Service_Directory – (403) Не авторизовано для доступа к этому ресурсу / api regex, чтобы найти строку в квадратных скобках База данных PHP Недопустимый аргумент для foreach () Drupal localhost перенаправляется на www.localhost.com Обнаружение браузеров старше двух лет Передача в 32-битное целое может привести к усечению PHP Propel? как получить текст из файла pdf и сохранить его в DB Пользовательские валидаторы Zend Framework 2 для форм

Обработка истекшего токена в Laravel

Каков наилучший способ обработки истекших жетонов в laravel 5.

Я имею в виду, что у меня есть страница, и у нее есть ссылки, которые выполняют запросы ajax. Они работают нормально, когда страница загружается, но когда я жду какое-то время, я получаю ошибку TOKEN MISMATCH.

Теперь мне нужно обновить страницу, чтобы она снова работала. НО, я не хочу обновлять страницу. Я хочу, чтобы какой-то способ обновить токен или какую-то другую работу, чтобы исправить ошибку.

Надеюсь, ты понял.

работа для него, заключается в том, чтобы фактически получить новый токен в определенное время, иначе вы побеждаете цель токена csrf:

<html> <head> <meta name="csrf_token" content="{{ csrf_token() }}"> </head> <body> <script type="text/javascript"> var csrfToken = $('[name="csrf_token"]').attr('content'); setInterval(refreshToken, 3600000); // 1 hour function refreshToken(){ $.get('refresh-csrf').done(function(data){ csrfToken = data; // the new token }); } setInterval(refreshToken, 3600000); // 1 hour </script> </body> </html> 

В маршрутах laravel

 Route::get('refresh-csrf', function(){ return csrf_token(); }); 

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

Я объединяю 2 вещи для этого случая:

1. Увеличьте продолжительность сеанса

 //In config/session.php replace this: 'lifetime' => 120 //with: 'lifetime' => 360 

Время жизни по умолчанию Laravel 5 равно 120 (минутам), вы можете изменить его на любое значение, например, 360 (6 часов)

2. Поймать исключение и отобразить сообщение об ошибке

 //In app/Exceptions/Handler.php replace this: public function render($request, Exception $e) { if ($e instanceof ModelNotFoundException) { $e = new NotFoundHttpException($e->getMessage(), $e); } return parent::render($request, $e); } //with: public function render($request, Exception $e) { if ($e instanceof ModelNotFoundException) { $e = new NotFoundHttpException($e->getMessage(), $e); } if ($e instanceof \Illuminate\Session\TokenMismatchException) { return redirect('/')->withErrors(['token_error' => 'Sorry, your session seems to have expired. Please try again.']); } return parent::render($request, $e); } 

Поэтому в основном вы перенаправляете пользователя на корень «/» (вы можете изменить его на любой путь) с сообщением об ошибке, и на этой странице вы должны сделать это, чтобы отобразить сообщение об ошибке:

 @if ($errors->has('token_error')) {{ $errors->first('token_error') }} @endif 

Я думаю, что ответ от @UX Labs вводит в заблуждение. И тогда комментарий от @jfadich кажется совершенно неправильным.

Для Laravel 5.4 в мае 2017 года я решил проблему следующим образом:

Вот ответ, который работает

В web.php :

 Route::post('keep-token-alive', function() { return 'Token must have been valid, and the session expiration has been extended.'; //https://stackoverflow.com/q/31449434/470749 }); 

В javascript, на ваш взгляд:

 $(document).ready(function () { setInterval(keepTokenAlive, 1000 * 60 * 15); // every 15 mins function keepTokenAlive() { $.ajax({ url: '/keep-token-alive', //https://stackoverflow.com/q/31449434/470749 type: 'post', headers: { 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') } }).then(function (result) { console.log(new Date() + ' ' + result + ' ' + $('meta[name="csrf-token"]').attr('content')); }); } }); 

Обратите внимание, что вы не должны VerifyCsrfToken.php 'keep-token-alive' в исключениях в VerifyCsrfToken.php . Поскольку @ ITDesigns.eu подразумевается в комментарии, для этого маршрута важно проверить, существует ли действующий токен и что ему просто нужно продлить срок его действия.

Почему этот подход решает мою проблему

Мой сайт Laravel позволяет пользователям смотреть видео (час), и он использует ajax для публикации своего прогресса каждую минуту.

Но многие пользователи загружают страницу, а затем не запускают видео до много часов спустя.

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

И тогда я получу тонны исключений TokenMismatch в своих журналах (и пропустил бы данные о их прогрессе).

В session.php я изменил 'lifetime' с 120 до 360 минут, но этого было недостаточно. И я не хотел делать это дольше 6 часов. Поэтому мне нужно было включить эту страницу, чтобы часто расширять сеанс с помощью ajax.

Как вы можете проверить это и понять, как работают токены:

В web.php :

 Route::post('refresh-csrf', function() {//Note: as I mentioned in my answer, I think this approach from @UX Labs does not make sense, but I first wanted to design a test view that used buttons to ping different URLs to understand how tokens work. The "return csrf_token();" does not even seem to get used. return csrf_token(); }); Route::post('test-csrf', function() { return 'Token must have been valid.'; }); 

В javascript, на ваш взгляд:

 <button id="tryPost">Try posting to db</button> <button id="getNewToken">Get new token</button> (function () { var $ = require("jquery"); $(document).ready(function () { $('body').prepend('<div>' + new Date() + ' Current token is: ' + $('meta[name="csrf-token"]').attr('content') + '</div>'); $('#getNewToken').click(function () { $.ajax({ url: '/refresh-csrf', type: 'post', headers: { 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') } }).then(function (d) { $('meta[name="csrf-token"]').attr('content', d); $('body').prepend('<div>' + new Date() + ' Refreshed token is: ' + $('meta[name="csrf-token"]').attr('content') + '</div>'); }); }); $('#tryPost').click(function () { $.ajax({ url: '/test-csrf', type: 'post', headers: { 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') } }).then(function (d) { $('body').prepend('<div>' + new Date() + ' Result of test: ' + d + '</div>'); }); }); }); })(); 

В session.php временно измените 'lifetime' на что-то очень короткое для целей тестирования.

Затем поиграйте.

Вот как я узнал, как работает токен Laravel и как нам просто нужно успешно отправлять POST на защищенный CSRF маршрут, чтобы токен оставался действительным.

Увеличьте время lifetime ваших сеансов. Вы можете сделать это, отредактировав файл config/session.php в своей конфигурации laravel.

 /* |-------------------------------------------------------------------------- | Session Lifetime |-------------------------------------------------------------------------- | | Here you may specify the number of minutes that you wish the session | to be allowed to remain idle before it expires. If you want them | to immediately expire on the browser closing, set that option. | */ 'lifetime' => 120, 

Я думаю, что лучший вариант – взять конфигурацию жизненного цикла файла config / session.php, а затем значение жизненного цикла, умноженное на 60 * 1000 в коде javascript. Используйте вспомогательную функцию config (), предоставляемую laravel, она может выглядеть так:

 <script type="text/javascript"> var timeout = ({{config('session.lifetime')}} * 60) * 1000; setTimeout(function() { //reload on current page window.location = ''; }, timeout); </script> 

Я знаю, что это не лучшее решение, но одно из самых простых. Просто отключите защиту CSRF для этой страницы, где пользователь проводит много времени. Например, на моем сайте они могут писать статью часами на одной странице. И это очень неприятно, если вы не можете сохранить статью из-за защиты CSRF.