情景:
相同的浏览器。
结果: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]
即使我从我的路线中删除了Route :: group(['中间件' =>' auth']组...在标签1中转到现在打开的网址会产生这个错误。我只是没有得到它。
我如何摆脱这个?
答案 0 :(得分:3)
我找出原因,但我不确定。希望你们其中一个人知道。
在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;
}
}
答案 1 :(得分: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);
}
但是如果你仔细观察,你会看到它在回报中检查:
$request->session()->token()
但是,会话为null
,因此您尝试从null请求方法时会遇到异常。
因此,如果我没有弄错的话,您只需要在handle
方法中为if添加额外的检查。
而不是:
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语句,该函数说明了所有内容。仅为了清晰的代码。
是其中之一,或者您可以考虑检查您的其他中间件,任何触及请求标头的人,并且可能会取消设置标题。
如果您使用StartSession中间件的handle
功能代码:
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 :(得分:0)
在从中间件返回响应时经历了类似的问题,我意识到这是由返回return view('my.view.blade')
而不是return response()->view('my.view.blade')
引起的。
所以简而言之,不要直接返回视图。将view()
助手链接到response()
助手。
return view('myview.blade'); //wrong
return response()->view('myview.blade'); //works