Laravel авария печенья 5 нуля
Сценарий:
Тот же браузер.
- Вкладка 1: вход в мое приложение laravel.
- Вкладка 2: вход в мое приложение laravel.
- Вкладка 2: выход из системы
- Вкладка 1: нажмите кнопку, которая вызывает перенаправление маршрута, который защищен: Route:: group (['middleware' = > 'auth'], function() {
...
Результат: Laravel 5 сработает, прежде чем он попадет в мой код:
![введите описание изображения здесь]()
Stack
Symfony\Component\Debug\Exception\FatalErrorException Call to a member function setCookie() on null
vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php:184 __construct
vendor/laravel/framework/src/Illuminate/Foundation/Bootstrap/HandleExceptions.php:131 fatalExceptionFromError
vendor/laravel/framework/src/Illuminate/Foundation/Bootstrap/HandleExceptions.php:116 handleShutdown
vendor/laravel/framework/src/Illuminate/Foundation/Bootstrap/HandleExceptions.php:0 addCookieToResponse
vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php:72 handle
vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php:125 Illuminate\Pipeline\{closure}
vendor/laravel/framework/src/Illuminate/Cookie/Middleware/AddQueuedCookiesToResponse.php:36 handle
vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php:125 Illuminate\Pipeline\{closure}
vendor/laravel/framework/src/Illuminate/Cookie/Middleware/EncryptCookies.php:40 handle
vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php:125 Illuminate\Pipeline\{closure}
vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/CheckForMaintenanceMode.php:42 handle
vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php:125 Illuminate\Pipeline\{closure}
vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php:101 call_user_func:{/home/vagrant/dev/opus-web-app/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php:101}
vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php:101 then
vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php:115 sendRequestThroughRouter
vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php:84 handle
public/index.php:53 {main}
public/index.php:0 [main]
Даже когда я удаляю группу Route:: group (['middleware' = > 'auth'] из моих маршрутов... переход на вкладку 1 к открытым URL-адресам приведет к этой ошибке. Я просто не получаю это.
Как мне избавиться от этого?
Ответы
Ответ 1
Мне кажется, что проблема заключается в вашей логике в проверке CSRF.
Вот проблема:
Вы проверяете, совпадают ли токены, и эта функция следующая:
protected function tokensMatch($request)
{
$token = $request->input('_token') ?: $request->header('X-CSRF-TOKEN');
if (! $token && $header = $request->header('X-XSRF-TOKEN')) {
$token = $this->encrypter->decrypt($header);
}
return Str::equals($request->session()->token(), $token);
}
Но если вы посмотрите внимательно, вы увидите, что в возврате он проверяет:
$request->session()->token()
Но сеанс null
, поэтому вы получите исключение для попытки запросить метод из null.
Итак, если я не ошибаюсь, все, что вам нужно сделать, это просто добавить дополнительную проверку в if, если в методе handle
.
Вместо этого:
if ($request && ((
$this->isReading($request)
|| $this->excludedRoutes($request)
|| ($this->tokensMatch($request) && Auth::check())
)))
У вас должно получиться следующее:
if ($request && ((
$this->isReading($request)
|| $this->excludedRoutes($request)
|| ($request->hasSession() && $this->tokensMatch($request) && Auth::check())
)))
Таким образом, если сеанс отсутствует, он даже не проверяет, соответствуют ли токены, и он не будет там сбой.
Вы также можете рассмотреть рефакторинг этой части оператора if функции, которая по имени описывает, что вы проверяете, и даже полный оператор if для функции, которая говорит все это. Просто для ясности кода.
Это либо, или вы можете рассмотреть возможность проверки своих других Middlewares, всех, кто касается заголовков запроса и потенциально может отключить заголовки.
Если вы берете код handle
функции промежуточного ПО StartSession:
public function handle($request, Closure $next)
{
$this->sessionHandled = true;
if ($this->sessionConfigured())
{
$session = $this->startSession($request);
$request->setSession($session);
}
// ** HERE ALL OTHER MIDDLEWARES ARE BEING CALL
$response = $next($request);
if ($this->sessionConfigured())
{
$this->storeCurrentUrl($request, $session);
$this->collectGarbage($session);
// ** AFTER ALL OTHER MIDDLEWARES ARE CALLED THE FOLLOWING FUNCTION
// TOUCHES THE HEADER AND IS NULL
$this->addCookieToResponse($response, $session);
}
return $response;
}
Итак, возможно, что где-нибудь в любом другом промежуточном программном обеспечении вы касаетесь заголовка и оставляете его нулевым, как указано в вашей ошибке.
Я надеюсь, что это поможет.
Ответ 2
Я понял причину, но я просто не уверен в этом. Надеюсь, кто-то из вас узнает.
В kernel.php:
У меня был 'App\Http\Middleware\VerifyCsrfToken'
, определенный в черном $middleware
, а не $routeMiddleware
. когда я переместил его в $routeMiddleware
, я перестал получать эту ошибку.
Содержимое VerifyCsrfToken:
class VerifyCsrfToken extends BaseVerifier {
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
if ($request && (($this->isReading($request) || $this->excludedRoutes($request) || ($this->tokensMatch($request) && Auth::check()))))
{
return $this->addCookieToResponse($request, $next($request));
}
return view('sessionOver');
}
protected function excludedRoutes($request)
{
$routes = [
'deployPush' // webhook push for bitBucket.
];
foreach($routes as $route)
if ($request->is($route))
return true;
return false;
}
}
Ответ 3
Может быть, это будет полезно для вас .check в промежуточном программном обеспечении некоторые считают похожими на это
public function handle($request, Closure $next)
{
$response = $next($request);
if ( ! Auth::user()) // Your logic here...
abort(403, 'Unauthorized action.');
return $response;
}
Ref:: https://laracasts.com/discuss/channels/general-discussion/disable-global-verifycsrftoken-and-use-as-middleware-doesnt-work-setcookie-on-null
в этом обсуждении обсуждалась некоторая ошибка cookie. Это может помочь вам
Ответ 4
Опытная аналогичная проблема возникла специально при возврате ответа от промежуточного программного обеспечения, и я понял, что это вызвано возвратом return view('my.view.blade')
, а не return response()->view('my.view.blade')
.
Короче говоря, не возвращайте представление напрямую. Закрепите помощника view()
помощнику response()
.
return view('myview.blade'); //wrong
return response()->view('myview.blade'); //works