场景:
同样的浏览器
结果: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会产生这个错误.我只是不明白.
我怎么摆脱这个?
在我看来,问题出在你检查 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)
因此,根据您的错误所述,在任何其他中间件中的某个地方,您可能会触摸标头并将其保留为空。
我希望这有帮助。