Laravel 5:404 路线上的会话

Posted

技术标签:

【中文标题】Laravel 5:404 路线上的会话【英文标题】:Laravel 5: Sessions on 404 route 【发布时间】:2016-09-05 15:31:05 【问题描述】:

这让我疯狂了好几个星期: 如何在 404 页面上提供会话?我只是 在我的默认模板中嵌入 404 错误页面。它还显示导航栏 和页脚,但如何让我的用户在 404 上保持登录状态?

在 404 Auth::check() 上总是返回 false,并且会话特定的所有其他内容都是 null 或空。

如何在 (404) 错误页面上启用会话?

【问题讨论】:

您找到答案了吗?我也有同样的问题。 @RobinvanBaalen 不幸的是:( 【参考方案1】:

对于 Laravel 5.5.5 或更高版本,只需使用 Route::fallback:

Route::fallback('PagesController@notFound');

这将帮助您自定义 404 视图以访问所有会话等内容。

【讨论】:

【参考方案2】:

我真的不明白这些答案中的任何一个有多棒。它们过于复杂,并倾向于建议使用额外的路由重建内核,从而导致内存和 cpu 使用量激增,只是为了创建一个 404 页面。

我建议只创建您需要的路线,而不是使用 Laravel 页面建议的自动错误页面。在较新版本的 Laravel 中,这一点得到了改进,但对于这个版本,我只推荐以下内容:

routes.php

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

显然取决于您的设置方式,这就是我使用路由并创建HttpErrorController 来处理路由的方式,这就是它已经在web 中间件组中的原因

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);

你可以以任何你认为合适的方式处理这些,在其中添加一个开关,检查它是否是一个 json 请求,然后以不同的方式处理等等

【讨论】:

【参考方案3】:

为避免出现其他异常或使用api中间件接收请求时出现问题,请将App/Exceptions/Handler.php中的渲染函数更改为:

 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);
    

【讨论】:

【参考方案4】:

所以我知道这是一个老问题,但如果有人觉得它有用,这就是我处理这个问题的方式:

在我的App/Exceptions/Handler.php 中,我将默认的render 方法更改为:

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);

这达到了两个要求:

    所有web 中间件都为请求正确运行 有效的 API 路由不会启动会话

这实际上是一个决定,将web 中间件组设置为在出现错误时运行的默认值。 Laravel 通常不会在错误页面上运行任何中间件组。如果需要或使用其他条件,例如,您当然可以指定其他中间件或其他路由参数。如果路径以api/ 开头,则使用api 中间件,而不是使其更加一致。

希望这对某人有所帮助。

【讨论】:

【参考方案5】:

只是对现有答案进行一些扩展:确保从 $middlewareGroups 中删除该中间件(如果它也存在的话),这样您就不会两次应用该中间件。

你会得到这样的结果:

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',
    ],
];

据我了解,这是因为处理会话的中间件,因为位于 web 组中,仅适用于在 web.php 上路由的那些页面。而且由于默认错误处理不会重定向到路由页面,因此我们无法访问会话。

这样中间件将应用于所有页面,而不仅仅是那些在 web.php 上路由的页面,包括错误页面。

我最初找到了here 的解决方案,但我花了一段时间才明白为什么会发生这种情况(我以为我完全搞错了,请随时确认或更正)。

希望它有所帮助,它在 Laravel 5.4 上对我有用

【讨论】:

这个解决方案一直让我退出【参考方案6】:

您可以做的是,在 app/http/Kernel.php 中添加以下代码块:

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

在 $middleware 变量中。所以它看起来像:

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

它对我有用,我希望它也对你有用。

【讨论】:

谢谢。你能解释一下为什么没有它就不能工作吗?这个改变有什么不同? 此更改会将会话中间件添加到每个请求中。如果您像我们一样拥有无状态 API 层,那么这不是解决方案,因为会话也会添加到您的 API 请求中。 谢谢..而且我认为您需要注销并登录。因为它没有在该页面上设置会话 ID。 更改后 laravel 验证错误不会显示在视图页面上。

以上是关于Laravel 5:404 路线上的会话的主要内容,如果未能解决你的问题,请参考以下文章

Laravel 5.2 - 会话不会在路由更改中持续存在

是否可以使用 API 令牌在 laravel 中进行用户模拟?

如果在 Laravel 5.1 中找不到路由,则显示 404 页面

Laravel 5.4 上的示例 PHPUnit 测试失败并显示 404

为啥我得到一个 404 到 laravel 5.7 公共子文件夹?

Laravel 在会话更改后显示 404