Laravel 5 null cookie崩溃

Jas*_*enX 11 php laravel

场景:

同样的浏览器

  1. 标签1:登录我的laravel应用程序.
  2. 标签2:登录我的laravel应用程序.
  3. 标签2:注销
  4. 选项卡1:单击一个按钮,该按钮导致重定向到受以下路由保护的路由:Route :: group(['middleware'=>'auth'],function(){...

结果:Laravel 5在进入我的代码之前崩溃:

在此输入图像描述

堆:

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]
Run Code Online (Sandbox Code Playgroud)

即使我从路由中删除了Route :: group(['middleware'=>'auth']组...在标签1中转到现在打开的URL会产生这个错误.我只是不明白.

我怎么摆脱这个?

Nes*_*ert 0

在我看来,问题出在你检查 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);
}
Run Code Online (Sandbox Code Playgroud)

但如果你仔细观察,你会发现它在返回中检查:

$request->session()->token()
Run Code Online (Sandbox Code Playgroud)

但是,会话是null这样的,当您尝试从 null 请求方法时会出现异常。

因此,如果我没有记错的话,您所需要做的就是在方法中的 if 中添加一个额外的检查handle。而不是这个:

if ($request && ((
      $this->isReading($request) 
      || $this->excludedRoutes($request) 
      || ($this->tokensMatch($request) && Auth::check())
    )))
Run Code Online (Sandbox Code Playgroud)

你应该有这个:

if ($request && ((
      $this->isReading($request) 
      || $this->excludedRoutes($request) 
      || ($request->hasSession() && $this->tokensMatch($request) && Auth::check())
   )))
Run Code Online (Sandbox Code Playgroud)

这样,如果没有会话,它甚至不会检查令牌是否匹配,并且不会在那里崩溃。

您还可以考虑将 if 语句的该部分重构为一个函数,该函数通过名称描述您正在检查的内容,甚至将完整的 if 语句重构为一个说明了全部内容的函数。只是为了代码清晰。


要么是这样,要么您可以考虑检查其他中间件,任何接触请求标头并可能取消标头设置的人。

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;
}
Run Code Online (Sandbox Code Playgroud)

因此,根据您的错误所述,在任何其他中间件中的某个地方,您可能会触摸标头并将其保留为空。

我希望这有帮助。