Laravel 5.8 从已清除的会话中单击注销后显示“419 页面已过期”
Laravel 5.8 showing "419 Page Expired" after clicking logout from an already cleared session
我 运行 php artisan make:auth 命令,我将逐步解释之后我做了什么以了解场景,
- 登录新会话(示例。com/home)
- 打开一个新标签并粘贴 url,即示例。com/home。
- 现在在同一个会话中打开了 2 个标签页。
- 我从其中一个选项卡中单击了注销,它工作得很好
- 然后,当我尝试从另一个选项卡注销时,它给我一个错误,提示“419 页面已过期”,即使重新加载后它也无处可去。
问题是,这种情况可能会出现,我不想看到这个错误信息,点击注销后就注销,即使会话已过期。
注意:这个问题不是因为没有添加@csrf
嗯,这是一个明显的消息,您可以尝试为该页面制作更好的布局,但显示它仍然很好,以便用户知道发生了什么。如果您想以不同的方式处理它,您可以尝试重定向到登录页面。
所以在渲染方法中的 app\Exceptions\Handler.php
文件中添加:
if ($exception instanceof \Illuminate\Session\TokenMismatchException) {
return redirect()->route('login');
}
恕我直言,您可以尝试修改您的 app/Http/Middleware/VerifyCsrfToken.php
文件。
用这样的东西编辑 $except 属性:
class VerifyCsrfToken extends Middleware
{
protected $except = [
'http://example.com/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
在一个 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')
];
}
}
问题的解决方法比较简单,需要对
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 Token 的保护。
您需要将 CSRF 令牌添加到您的表单中:
<form action="{{ route('logout') }}" method="POST">
@csrf
<button type="submit" class="btn nav-link">Logout</button>
</form>
永远不会太晚)
添加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);
}
我认为这些是最好的解决方案。
我 运行 php artisan make:auth 命令,我将逐步解释之后我做了什么以了解场景,
- 登录新会话(示例。com/home)
- 打开一个新标签并粘贴 url,即示例。com/home。
- 现在在同一个会话中打开了 2 个标签页。
- 我从其中一个选项卡中单击了注销,它工作得很好
- 然后,当我尝试从另一个选项卡注销时,它给我一个错误,提示“419 页面已过期”,即使重新加载后它也无处可去。
问题是,这种情况可能会出现,我不想看到这个错误信息,点击注销后就注销,即使会话已过期。
注意:这个问题不是因为没有添加@csrf
嗯,这是一个明显的消息,您可以尝试为该页面制作更好的布局,但显示它仍然很好,以便用户知道发生了什么。如果您想以不同的方式处理它,您可以尝试重定向到登录页面。
所以在渲染方法中的 app\Exceptions\Handler.php
文件中添加:
if ($exception instanceof \Illuminate\Session\TokenMismatchException) {
return redirect()->route('login');
}
恕我直言,您可以尝试修改您的 app/Http/Middleware/VerifyCsrfToken.php
文件。
用这样的东西编辑 $except 属性:
class VerifyCsrfToken extends Middleware
{
protected $except = [
'http://example.com/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
在一个 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')
];
}
}
问题的解决方法比较简单,需要对 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 Token 的保护。
您需要将 CSRF 令牌添加到您的表单中:
<form action="{{ route('logout') }}" method="POST">
@csrf
<button type="submit" class="btn nav-link">Logout</button>
</form>
永远不会太晚)
添加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);
}
我认为这些是最好的解决方案。