在Laravel中发布请求-错误-419对不起,您的会话/ 419您的页面已过期


88

我安装了Laravel 5.7

向文件添加了表格 \resources\views\welcome.blade.php

<form method="POST" action="/foo" >
    @csrf
    <input type="text" name="name"/><br/>
    <input type="submit" value="Add"/>
</form>

已添加到文件 \routes\web.php

Route::post('/foo', function () {
    echo 1;
    return;
});

发送POST请求后:

419对不起,您的会话已过期。请刷新,然后重试。

在版本5.6中,没有这样的问题。


您是否尝试过添加重定向?代替return;您可以打电话return redirect()->back();。据我所知,该应用程序在发布请求后无事可做。也许您可以在处理请求后将其重定向到视图。
dcangulo

1
我有同样的问题。当我切换到数据库会话时,会发生这种情况,当我改回filefor时SESSION_DRIVER.env它会正常工作。为什么基于数据库的会话不起作用。
Junaid Qadir '18

我将您的确切代码复制到了新的laravel 5.7安装中。有效。在其他地方有问题。
凯尔·沃德尔

这个问题是因为令牌问题。我已经尝试运行相同的代码,但是没有错误。您应该在表单中提供更多信息,例如会话驱动程序,_token值显示。另外,您可以在此文件vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/VerifyCsrfToken.php行67中调试自己,以了解原因
bangnokia

1
我意识到我曾将sessions桌子用于其他目的。将表名更改为更合适的表名并运行artisan session:table并刷新迁移后,一切工作正常
Junaid Qadir

Answers:


113

在阅读以下内容之前,请确保您具有@csrf{{ csrf_field() }}格式

<form method="post">
@csrf <!-- {{ csrf_field() }} -->
... rest of form ...
</form>

larvel中出现Session Expired或419 Page Expired错误消息是因为您的csrf令牌验证失败的某处,这意味着App\Http\Middleware\VerifyCsrfToken::class中间件已打开。@csrf已经以Blade指令的形式添加了它,也应该很好。

然后要检查的另一个区域是会话。该csrf令牌验证直接涉及您的会话,所以你可能要检查你的会话驱动程序是否工作正常与否,如不正确配置的Redis可能会导致问题。

也许您可以尝试从.env文件中切换会话驱动程序/软件,下面提供了受支持的驱动程序

Laravel 5,Laravel 6和Laravel 7中受支持的会话驱动程序 (Doc Link)

  • file -会话存储在存储/框架/会话中。
  • cookie -会话存储在安全的加密cookie中。
  • database -会话存储在关系数据库中。
  • memcached/ redis-会话存储在这些快速,基于缓存的商店之一。
  • array -会话存储在PHP数组中,并且不会保留。

如果在切换会话驱动程序后您的表单可以工作,则说明该特定驱动程序有问题,请尝试从那里修复错误。

可能的容易出错的情况

  • 由于/storage目录的权限问题,可能基于文件的会话可能无法正常工作(快速搜索将为您带来解决方案),还要记住,将777用作目录绝对不是解决方案。

  • 对于数据库驱动程序,您的数据库连接可能错误,或者sessions表可能不存在或配置错误(根据@Junaid Qadir的评论,错误的配置部分已确认是问题)。

  • redis/memcached 配置错误或同时被系统中的其他一些代码操纵。

执行php artisan key:generate并生成一个新的应用程序密钥可能是一个好主意,该应用程序密钥又将刷新会话数据。

清除浏览器缓存HARD,我发现chrome和firefox是我不记得的罪魁祸首。

阅读有关为何应用程序键如此重要的更多信息


1
有时仅仅是浏览器(主要是Chrome)不会设置Set-Cookie会话值,因为它的格式不正确或不标准。因此,Laravel不会从HTTP请求中找到任何现有会话值来与_token从FORM接收到的值进行比较。避免使用SESSION_DOMAIN=...Chrome和HTTP Cookie规范认为不安全的IP 。
KeitelDOG

我有同样的问题,但是我并没有不断收到该错误。它只是不时发生。我想这意味着会话驱动程序没有问题,因为它可以在99%的时间内工作。但是我正在运行一个实时应用程序,我不时收到客户的投诉。但是,这非常罕见。我正在使用文件会话驱动程序。有人知道为什么发生这种情况吗?谢谢您
-TheAngelM97

@ TheAngelM97您可以通过登录或注册页面轻松重现此错误。可能超过30分钟不要做任何事情。然后,当您单击提交时,将419 Page Expired显示出来。出于可用性考虑,您如何告诉一个简单的用户刚刚发生了什么以及如何解决?
Pathros

38

这是因为表单需要一个csrf。在5.7版中,他们将其更改为@csrf

<form action="" method="post">
    @csrf
    ...

推荐人:https://laravel.com/docs/5.7/csrf


6
他的表格包括一个csrf令牌。不知道他以后是否编辑它。
eResourcesInc

是的,他的表格最初有一个csrf字段,我只是研究了编辑历史
Dexter Bengil,

13

情况1:如果您正在本地系统中运行项目,例如127.0.01:8000,

然后

SESSION_DOMAIN=在您的.env文件中添加

或在您的config / session.php中 'domain' => env('SESSION_DOMAIN', ''),

然后运行 php artisan cache:clear

情况2:如果项目正在服务器上运行,并且您具有“ mydomain.com”之类的域

SESSION_DOMAIN=mydomain.com在您的.env文件中添加

或在您的config / session.php中 'domain' => env('SESSION_DOMAIN', 'mydomain.com'),

然后运行 php artisan cache:clear




7

试评出来\App\Http\Middleware\EncryptCookies::class\app\Http\Kernel.php 我有类似的问题,这样做解决了这个问题。可能不是最好的解决方案,因为安全性,但至少可以起作用。

以前我尝试过:

  • 清除缓存
  • 产生新的应用程式金钥
  • 在各种浏览器(Chrome 70,Mozilla Firefox 57和IE 11)中运行我的应用
  • 在另一台计算机上运行我的应用
  • 注释掉\App\Http\Middleware\VerifyCsrfToken::class\app\Http\Kernel.php
  • 注释掉\Illuminate\Session\Middleware\AuthenticateSession::class\app\Http\Kernel.php
  • 升级和降级Laravel(介于5.6和5.7之间)

但是以上这些都不适合我。

编辑

我的情况是每次登录时都会创建一个新的会话文件(旧的会话文件仍然存在,但突然被遗忘了。 storage/framework/sessions),并生成了新的CSRF令牌。因此,问题不在于VerifyCsrfToken。

正如@Vladd在评论部分中提到的那样,您永远不应该将其注释掉\App\Http\Middleware\VerifyCsrfToken::class。您必须检查是否已将正确的CSRF令牌发送到服务器。


1
在您提到的这些方式中,仅注释掉\ app \ Http \ Kernel.php中的\ App \ Http \ Middleware \ VerifyCsrfToken :: class对我有用。
莱克斯软

1
清除缓存,生成新的应用程序密钥+删除Cookie
Dobs'4

您永远都不会修改\ App \ Http \ Middleware \ VerifyCsrfToken :: class。为什么要这么做?要在应用中创建自己的弱点?
Vladd

@dobs感谢您添加“ +删除Cookie”,因为即使进行了所有可能的操作后,我仍然遇到419错误,并且仅当我清除浏览器cookie /以隐身方式尝试时,该错误才起作用。
Niraj Pandey

6

将您@csrf的welcome.blade.php更改为<input type="hidden" name="_token" value="{{ csrf_token() }}">

所以你的代码是这样的:

<form method="POST" action="/foo" >
    <input type="hidden" name="_token" value="{{ csrf_token() }}">
    <input type="text" name="name"/><br/>
    <input type="submit" value="Add"/>

   <button type="submit">Submit</button>
</form>

6

您的会话可能有问题。经过这些设置后,我解决了我的问题。对我而言,这是最后的选择。

  • 如果您使用“文件”作为会话驱动程序,那么刷新后是否保存了会话,请查看存储/框架/会话。如果不是,则很可能是由于文件夹权限不正确。检查您的存储/文件夹是否具有正确的权限
  • 尝试禁用页面中的所有Javascript(通过导航器或在代码内部将其禁用),并确保'http_only'=> true,
  • 尝试在不使用https的情况下使用
  • 确保SESSION_DRIVER变量不为null
  • 尝试在'encrypt'=> false和'encrypt'=> true之间切换,
  • 尝试更改cookie名称'cookie'=>'laravelsession',
  • 尝试将SESSION_DOMAIN设置为您的实际域,或者将其设置为null
  • 尝试在'secure'=> env('SESSION_SECURE_COOKIE',false)和'secure'=> env('SESSION_SECURE_COOKIE',true)之间切换,

来源:Laravel会话始终会更改Laravel 5.4中的每次刷新/请求


是的,在尝试了许多其他操作之后,SESSION_SECURE_COOKIE开关(将其更改为false)为我做了。(上localhost:8000
Marten Koetsier

SESSION_SECURE_COOKIE也是我的问题,我在遵循网站优化指南时对它进行了更改。
布拉姆·詹森,

对我来说,它可以与https一起使用,但不能与http一起使用...知道为什么吗?感谢您的出色回答,我花了几个小时才找到它。
sharkyenergy


4

要解决此错误,您首先需要在form标签中插入以下命令之一。

@csrf 要么 {{ csrf_field }}

如果您的问题仍未解决,请执行以下操作:(请注意,以上命令之一必须位于form标记中)

1.将以下命令之一插入表单标签 @csrf{{ csrf_field }}

2.打开.env文件并将值更改为SESSION_DRIVER部分中的“文件”。

3.然后您应该重置laravel缓存。在终端中键入以下命令

php artisan view:clear php artisan route:clear php artisan cache:clear

php artisan config:cache

4.在最后一步,从服务中拔出项目,然后再次单击php artisan服务

希望您的问题得到解决


3

经过这么多时间我就解决了

我的laravel安装路径与配置文件session.php中设置的路径不同

'domain' => env('SESSION_DOMAIN', 'example.com'),

2

可能矫over过正,但是您可以尝试以下方法:

//表单调用添加了隐藏令牌字段的命名路由。

<form method="POST" action="{{ route('foo') }}" >
    @csrf
    <input type="hidden" name="_token" value="{!! csrf_token() !!}">
    <input type="text" name="name"/><br/>
    <input type="submit" value="Add"/>
</form>

//命名路线

Route::post('/foo', function () {
    return 'bar';
})->name('foo');

//将其添加到代码<head></head>块中:

<meta name="_token" content="{!! csrf_token() !!}" />

我确实在Laravel 5.7上使用Homestead在本地进行了测试,这是使用Laravel Installer 2.0.1全新安装的,并且可以正常工作。您的环境是什么?

理论:我想知道这是否{{ }}{!! !!}在环境中使用vs进行刀片渲染html标签有关,或者与您的服务方式有关(例如php artisan serve)。是什么让我觉得是line 335/vendor/laravel/framework/src/illuminate/Foundation/helpers.php应该呈现在同一行上述手动输入了。


是的,很酷,但是<meta>标签应该放在<head>,而不是中<body>。我不确定HTML验证程序是否会这样。
emix

我会说你是正确的,应该将它放在首位。
jeremykenedy

2

代码中没有问题。我已经检查了与新安装相同的代码。

表格代码:

<form method="POST" action="/foo" >
    @csrf
    <input type="text" name="name"/><br/>
    <input type="submit" value="Add"/>
</form>

web.php 文件代码:

Route::get('/', function () {
    return view('welcome');
});

Route::post('/foo', function () {
    echo 1;
    return;
});

提交表格后的结果是: 提交表格后的输出

如果您清除浏览器缓存或尝试使用其他浏览器,我认为它将解决。


2

一种快速的错误方法是转到app \ http \ middleware \ verifycsrftoken.php并将路由添加到$ except列表中。该发布请求将对CSRF令牌验证无效。

protected $except = [
    //
    'doLogin.aspx',
    'create_coupon',
];

2

419 | 页面,此错误意味着laravel安全问题,这意味着csrf令牌字段未正确使用。

使用{{csrf_field}} ,您的问题将得到解决。


2

如果您尝试所有这些步骤,它将正常工作:

  1. 确保会话配置正确,最简单的方法是将其设置为文件,并确保存储文件夹具有chmod 755权限,然后按.env如下所示进行设置,文件会话驱动程序是最简单的设置方法。

    SESSION_DRIVER=file
    SESSION_DOMAIN=
    SESSION_SECURE_COOKIE=false
    
  2. 确保Cache文件夹已清除且可写,您可以通过在artisan命令下面运行来实现。

    php artisan cache:clear
    
  3. 确保正确设置文件夹权限,它们的配置应如下所示:

    sudo chmod -R 755 storage
    sudo chmod -R 755 vendor
    sudo chmod -R 644 bootstrap/cache
    
  4. 确保您的表单中包含@csrf令牌。

希望这能解决您的问题。


1

在你的 Http/Kernel.php

尝试对此行发表评论:

\Illuminate\Session\Middleware\AuthenticateSession::class,

在您的Web中间件阵列中

这可能是您问题的根源


1

默认情况下,我没有这个问题。所以我要做的就是chmod -R 644 sessions 复制问题。

在此处输入图片说明

之后,我授予了会话文件夹的权限 chmod -R 755 sessions

现在,我的项目代码再次起作用。

在此处输入图片说明

发生这种情况的原因是您将高速缓存存储在缺少写入权限的文件上。

会话配置文件存储在config / session.php中。确保查看此文件中可用的选项。默认情况下,Laravel配置为使用文件会话驱动程序,该驱动程序对于许多应用程序都可以很好地工作。在生产应用程序中,您可以考虑使用memcached或redis驱动程序来提高会话性能。

解决方案:

1-正如我在上面确定的,您可以将755权限授予session文件夹。2-您可以使用其他会话驱动程序配置。

文件-会话存储在存储器/框架/会话中。cookie-会话存储在安全的加密cookie中。数据库-会话存储在关系数据库中。memcached / redis-会话存储在这些基于缓存的快速存储之一中。数组-会话存储在PHP数组中,并且不会持久保存。

记住; 如果要使用memcached / redis,则需要在服务器上安装它们,否则docker redis容器必须正在运行。


1

实际上,CSRF是基于会话的令牌。在路由组中添加您的路由,并添加一个控制会话的中间件。

Web是laravel中的默认中间件,它可以控制会话请求。

Route::group(array('middleware' => ['web']), function () {
  Route::post('/foo', function () {
     echo 1;
     return;
  });
});

1

如果您已经有csrf指令,则可能已更改了会话的运行方式。

在中config/session.php,选中“安全”字段。如果您的服务器上没有https,则应为false。

你也可以把SESSION_SECURE_COOKIE=FALSE你的.env文件(根目录)。


1

在项目上打开命令行cmd。

1.命令

php artisan config:cache

2.命令

php artisan route:clear

1

您的应用程序标头中是否还包含csrf?

<meta name="csrf-token" content="{{ csrf_token() }}">

1

尽管有表单@csrf,但仍显示419 pages has expired

SESSION_SECURE_COOKIE在config / session.php中将update选项设置为false后解决了它

'secure' => env('SESSION_SECURE_COOKIE', false)

比清除缓存


1

转到config / sessions.php

找到行

'secure' => env('SESSION_SECURE_COOKIE', true),

将其更改为false

'secure' => env('SESSION_SECURE_COOKIE', false),

如果将此参数设置为TRUE,浏览器将要求您使用HTTPS协议,否则它将不存储会话。由于无效


1

我只是遍历了所有内容,然后将鼠标悬停在此处以寻求答案。就我而言,解决方案是清除浏览器历史记录。



0

我只是遇到了同样的问题,这完全取决于我的愚蠢。在提交所述表单之前,我已经通过javascript禁用了所有表单字段(而不仅仅是提交按钮)!当然,这导致未提交所有表单元素(包括隐藏的_token字段),这又引发了419错误!

我希望这可以帮助某人从头几个小时开始抓挠!

禁用的表单输入未出现在请求中


0

我很久以前就遇到了这个问题。我记得它引起的许可storage/framework/sessions。您可能想通过chmod -R 0777 storage/framework/sessions命令进行更改。它为我工作。


0

就我而言,这很荒谬。Auth::routes()将路由文件放在顶部时,出现错误419 。

Auth::routes();

Route::middleware('auth')->group(function () {
    Route::get('/', 'DashboardController@index')->name('dashboard');
});

然后我通过移到Auth::routes();路由文件的底部来修复该错误。

Route::middleware('auth')->group(function () {
    Route::get('/', 'DashboardController@index')->name('dashboard');
});

Auth::routes();

也许它也可以帮助您解决问题。祝好运。


0

请注意,如果您尝试上载的大小超过发布文件大小限制的大文件,则会收到错误419。在这种情况下,您可以将upload_max_filesize和post_max_size都增加到一个合理的数量(例如10M或20M取决于您的用例和资源),请在此处检查: https //stackoverflow.com/a/2184541/2100489

但这可能会导致资源消耗问题,例如带宽和存储。作为解决方案,您可以在提交表单之前检查文件大小并显示警告消息。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.