从已清除的会话中单击注销后,Laravel 5.8显示“ 419页已过期”

时间:2019-07-18 12:41:58

标签: php laravel laravel-5 laravel-5.8

我运行 php artisan make:auth 命令,然后我将逐步解释该操作,以了解该情况,

  • 登录到新会话(example.com/home)
  • 打开一个新标签并粘贴URL,即example.com/home。
  • 现在在同一会话中打开2个标签。
  • 我从其中一个选项卡单击了注销,它运行得很好
  • 然后,当我尝试从另一个选项卡注销时,它给我一个错误,提示“ 419页已过期”,即使重新加载后也无济于事。

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

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

6 个答案:

答案 0 :(得分:3)

在Laravel 6项目中,我最终按如下方式修改了VerifyCsrfTokenMiddleware

您将看到,我只是将名为logout的路由添加到排除列表中。

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

<?php

namespace App\Http\Middleware;

use Illuminate\Contracts\Encryption\Encrypter;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken 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  \Illuminate\Contracts\Foundation\Application  $app
     * @param  \Illuminate\Contracts\Encryption\Encrypter  $encrypter
     * @return void
     */
    public function __construct(Application $app, Encrypter $encrypter)
    {
        parent::__construct($app, $encrypter);
        $this->except = [
            route('logout')
        ];
    }
}

答案 1 :(得分:3)

该问题的解决方案相对简单,并且除 VerifyCsrfToken中间件;

use Closure;


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

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

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

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

如果两个都成立,那么我们将'logout'添加到except数组中。然后,我们将控制权传递给核心VerifyCsrfMiddleware,该软件识别阵列中注销路由的存在,并绕过检查。表单数据已正确发布,并使用LogoutResponse重定向了我们。

用户看不到错误页面。

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

答案 2 :(得分:1)

这显然是一条消息,您可以尝试为该页面进行更好的布局,但是仍然可以很好地显示它,以便用户知道发生了什么。如果您希望以其他方式处理它,则可以尝试重定向到登录页面。

因此,在render方法内的app\Exceptions\Handler.php文件中添加以下内容:

if ($exception instanceof \Illuminate\Session\TokenMismatchException) {
    return redirect()->route('login');
}

答案 3 :(得分:1)

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

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

答案 4 :(得分:1)

<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

答案 5 :(得分:0)

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

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

Laravel 8.x Docs