Laravel 5: Sessions on 404 route

余生长醉 提交于 2020-01-10 04:59:08

问题


This is driving me crazy for weeks now: How can I make sessions available on the 404 page? I just embed the 404 error page in my default template. It also shows the navbar and the footer but how can I keep my user logged in when on a 404?

On a 404 Auth::check() always returns false and every else whats session specific is null or empty.

How to enable sessions on (404) error pages?


回答1:


What you can do is, inside the app/http/Kernel.php add the follwing block of code:

    \Illuminate\Session\Middleware\StartSession::class,
    \Illuminate\View\Middleware\ShareErrorsFromSession::class,

Inside the $middleware variable. So it would look like:

    protected $middleware = [
    \Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
    \Illuminate\Session\Middleware\StartSession::class,
    \Illuminate\View\Middleware\ShareErrorsFromSession::class,
    ];

It worked for me, I hope it works for you as well.




回答2:


So I know this is an old question but in case anyone finds it useful here's how I've dealt with this:

In my App/Exceptions/Handler.php I changed the default render method to:

public function render($request, Exception $exception) {        
    \Route::any(request()->path(), function () use ($exception, $request) {
        return parent::render($request, $exception);
    })->middleware('web');
    return app()->make(Kernel::class)->handle($request);
}

This achieves 2 requirements:

  1. All the web middleware run correctly for the request
  2. Valid API routes do not start the session

This is in practice a decision to make the web middleware group the default to run when there's an error. Laravel would normally not run any middleware group on error pages. You can of course specify additional middleware or other route parameters if you want or use other conditions like e.g. if the path starts with api/ then use the api middleware instead making it more consistent.

Hopefully this is helpful to someone.




回答3:


Just to expand a bit on the existing answer: make sure to remove that middleware from $middlewareGroups if it's also there, so you don't apply the middleware twice.

You'll end up with something like this:

protected $middleware = [
    \Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
    \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
    \App\Http\Middleware\TrimStrings::class,
    \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
    \Illuminate\Session\Middleware\StartSession::class,
    \Illuminate\Session\Middleware\AuthenticateSession::class,
    \Illuminate\View\Middleware\ShareErrorsFromSession::class,
];

protected $middlewareGroups = [
    'web' => [
        \App\Http\Middleware\EncryptCookies::class,
        \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
        //\Illuminate\Session\Middleware\StartSession::class,
        //\Illuminate\Session\Middleware\AuthenticateSession::class,
        //\Illuminate\View\Middleware\ShareErrorsFromSession::class,
        \App\Http\Middleware\VerifyCsrfToken::class,
        \Illuminate\Routing\Middleware\SubstituteBindings::class,
    ],

    'api' => [
        'throttle:60,1',
        'bindings',
    ],
];

As far as my understanding goes this was caused because the middleware that deals with the session, by being at the web group was being applied only to those pages routed on web.php. And since the default error handling does not redirect to a routed page we had no access to the session.

This way the middleware will be applied to all pages, and not only to those routed on web.php, including the error ones.

I originally found the soution here, but took me a while to understand why this was happening (thought i cold have gotten it all wrong, feel free to confirm or correct this please).

Hope it helps, it's working for me on Laravel 5.4




回答4:


To avoid problems when you have other exception or recive request with api middleware,change the render function In App/Exceptions/Handler.php to :

 public function render ($request, Exception $exception)
{
    if ($this->isHttpException($exception)) {
        switch ($exception->getStatusCode()) {
            case '404':
                \Route::any(request()->path(), function () use ($exception, $request) {
                    return parent::render($request, $exception);
                })->middleware('web');
                return app()->make(Kernel::class)->handle($request);
                break;
            default:
                return $this->renderHttpException($exception);
                break;
        }
    } else {

        return parent::render($request, $exception);
    }
}



回答5:


I don't really see how any of these answers are great. They are over complicated and tend to suggest to rebuild the kernel with an additional route, causing a spike in memory and cpu usage just to make a 404 page.

I suggest just creating the route you need, and not using the automatic error pages that the Laravel pages suggest. In newer versions of Laravel this has been improved, but for this version I just recommend the following:

routes.php

Route::group(['middleware' => ['web']], function ($router) {
    $router->get('/404', [
        'uses' => 'HttpErrorController@404',
        'as' => 'errors.404',
    ]);
});

Obviously depending on how you are set up, this is how I'd use the routes and create a HttpErrorController to handle the route, this why it's already in the web middleware group

App\Exceptions\Handler.php

public function render($request, Exception $exception) 
{

    if ($this->isHttpException($exception) && $exception->getStatusCode() === 404) 
    {
        return redirect()->route('404');
    }

    return parent::render($request, $exception);
}

You can handle these any way you see fit, add a switch in there, check if it's a json request and then handle that differently etc



来源:https://stackoverflow.com/questions/37142168/laravel-5-sessions-on-404-route

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!