Laravel 5.8 在单击已清除会话注销后显示"419 Page Expired"



我运行 php artisan make:auth 命令,我将逐步解释之后我做什么来理解场景,

  • 登录到新会话 (example.com/home(
  • 打开一个新选项卡并粘贴 URL,即 example.com/home。
  • 现在,使用同一会话打开了 2 个选项卡。
  • 我从其中一个选项卡中单击注销,它工作得很好
  • 然后,当我尝试从另一个选项卡注销时,它给了我一个错误,说"419页面已过期",即使重新加载后它也无处可去。

问题是,可能会出现这些情况,我不想看到此错误消息,只需在单击注销后注销,即使会话已过期。

注意:此问题不是因为未添加@csrf

嗯,这是一个明显的消息,你可以尝试为该页面制作更好的布局,但仍然最好显示它,以便用户知道发生了什么。如果您想以不同的方式处理它,您可以尝试重定向到登录页面。

因此,在渲染方法的appExceptionsHandler.php文件中,添加以下内容:

if ($exception instanceof IlluminateSessionTokenMismatchException) {
    return redirect()->route('login');
}

该问题的解决方案相对简单,需要对验证CsrfToken中间件;

use Closure;

    public function handle($request, Closure $next)
    {
        if(!Auth::check() && $request->route()->named('logout')) {
        
            $this->except[] = route('logout');
            
        }
        
        return parent::handle($request, $next);
    }

通常,此文件仅包含应从 csrf 忽略的路由$except数组。

在此代码中,我们重写 handle 方法并执行两项检查。

  • 用户是访客(即,不使用经过身份验证的会话(,并且,
  • 是注销路由的路由

如果两者都为真,那么我们将"注销"添加到 except 数组中。 然后,我们将控制权传递给核心 VerifyCsrfMiddleware,该中间件识别阵列中是否存在注销路由,并绕过检查。表单数据已正确发布,我们使用注销响应重定向。

用户看不到错误页面。

通过以这种方式检查,我们确保CSRF令牌仍然保护真正的注销请求。

永远不会

太晚(

添加 app/Http/Middleware/VerifyCsrfToken.php

    use Closure;
    public function handle($request, Closure $next)
    {
        if($request->route()->named('logout')) {
            if (auth()->check()) {
                auth()->logout();
            }
            return redirect('/');
        }
    
        return parent::handle($request, $next);
    }

我认为这些是最好的解决方案。

我直言,您可以尝试修改app/Http/Middleware/VerifyCsrfToken.php文件。使用如下所示的内容编辑 $except 属性:

class VerifyCsrfToken extends Middleware
{       
    protected $except = [
        'http://example.com/logout',
    ];

在 Laravel 6 项目中,我最终修改了VerifyCsrfTokenMiddleware

如下

如您所见,我只是将logout命名的路由添加到排除列表中。

我覆盖了__construct函数,因为我们在初始化新变量时无法使用route()函数

<?php
namespace AppHttpMiddleware;
use IlluminateContractsEncryptionEncrypter;
use IlluminateContractsFoundationApplication;
use IlluminateFoundationHttpMiddlewareVerifyCsrfToken as Middleware;
class VerifyCsrfToken extends Middleware
{
    /**
     * Indicates whether the XSRF-TOKEN cookie should be set on the response.
     *
     * @var bool
     */
    protected $addHttpCookie = true;
    /**
     * The URIs that should be excluded from CSRF verification.
     *
     * @var array
     */
    protected $except = [
    ];
    /**
     * Create a new middleware instance.
     *
     * @param  IlluminateContractsFoundationApplication  $app
     * @param  IlluminateContractsEncryptionEncrypter  $encrypter
     * @return void
     */
    public function __construct(Application $app, Encrypter $encrypter)
    {
        parent::__construct($app, $encrypter);
        $this->except = [
            route('logout')
        ];
    }
}
<a href="{{ route('logout') }}" class="dropdown-item notify-item"="event.preventDefault(); document.getElementById('logout-form').submit();">
    <i class="fa fa-power-off"></i>  <span>{{ __('Logout') }} </span>
    </a>
<form id="logout-form" action="{{ route('logout') }}" method="POST" style="display: none;">
  @csrf
</form>

您错过了注销表单中的@csrf,因此只有您收到错误 419

您需要将 CSRF 令牌添加到表单中:

<form action="{{ route('logout') }}" method="POST">
    @csrf
    <button type="submit" class="btn nav-link">Logout</button>
</form>

拉维尔 8.x 文档

相关内容

最新更新