Laravel 419错误-VerifyCsrfToken问题

时间:2018-10-11 16:11:52

标签: php laravel csrf-protection laravel-middleware

我在同一台服务器上托管了多个Laravel网站。使用我创建的最新网站,联系表单将拒绝提交,而不会引发419错误。就像其他网站一样,我已经在web.php文件中设置了路由,这些网站具有实时有效的联系表单,并且我以完全相同的方式生成和发送令牌-使用{{ csrf_field() }}

我找到了一个类似问题的答案,指出您可以通过将条目添加到$except中的app/Http/Middleware/VerifyCsrfToken.php数组中来禁用Csrf检查。我已验证这确实可以解决419错误:

protected $except = [
    'contact',
    'contact*',
];

但是我当然希望保留Csrf功能,并且我仅更新了$except数组以获取故障排除值。

有人知道新的Laravel环境尽管传递了生成的令牌但仍具有419的行为可能有什么不同吗?我尝试过更新许多ENV设置并切换不同的内容,但是除了修改$except数组之外,其他都没有对该问题产生任何影响。

更新

由于到目前为止已经进行了一些讨论,所以我想我会提供一些其他信息和代码。

首先,这是一个ajax形式,但请不要跳出座位。我一直在测试有无ajax的表单。如果要使用ajax进行测试,只需单击与jQuery侦听器连接的按钮。如果没有,我将更改或删除按钮的ID,或者在控制台窗口中运行$("#formName").submit();

以上内容(ajax,老式提交以及带有.submit();的jquery选择器)都导致完全相同的响应-419错误。

为了完整起见,这是我的ajax代码,可在我托管的所有其他网站上使用。我定义了一个postData数组以保持其整洁,并在它之后直接添加了一个console.log()语句,以(再次)确认令牌生成得很好并且可以正确地与请求一起传递。

var postData = {

    name: $("#name").val(),
    email: $("#email").val(),
    message: $("#message").val(),

    _token: $("input[name=_token]").val()

};

console.log(postData);


$.post("/contact", postData, function (data) {

...

有什么想法吗?我的ENV或其他文件可能存在配置问题吗?

进度更新!

由于其他站点都可以正常工作,因此我克隆了一个旧站点,并简单地覆盖了为新网站更改的文件,然后变得更加糟糕!现在正在工作。多做一点挖掘,我在网站的克隆版本和非工作版本上运行了php artisan --version,结果如下:

  

工作版本:Laravel Framework 5.7.3

     

非工作版本:Laravel Framework 5.7.9

也许这是Laravel的错误?还是服务器上的某些软件包已过时,需要更新才能与新版本的Laravel一起使用?

7 个答案:

答案 0 :(得分:0)

刚刚在框架存储库中找到了您的问题。 这不是laravel问题,您的安装缺少对存储文件夹的写入权限,因此laravel无法写入会话,日志等。

由于无法写入文件,因此无法创建sessionn,因此无法验证csrf令牌,因此出现419错误。

快速修复:chmod -R 777 storage

正确的解决方法:将您的安装移动到nginx / apache /您的用户实际可以写的文件夹中。 如果您使用的是nginx / apache,请在此处移动您的应用并为项目(chown -R www-data: /path-to-project)授予正确的权限 如果您使用的是php artisan serve,请更改其对用户的权限:chown -R $(whoami) /path-to-project

你明白了,让作家们写作,你就很好。

答案 1 :(得分:0)

看看我对这个问题的回答是否对您想要达到的目标Form post request return error 419 unknown status laravel有帮助

答案 2 :(得分:0)

运行此命令 php artisan key:generate

答案 3 :(得分:0)

您的浏览器地址栏中的域可能与domain配置文件中的config/session.php键或环境文件中的SESSION_DOMAIN不匹配。

答案 4 :(得分:0)

TLDR:这篇文章包含许多潜在的问题和修复程序;它适用于那些卡住时寻找相关奖金信息的人。

我刚刚在看起来不正确的中间件安装中使用Laravel Sanctum遇到此错误。 Sanctum使用auth:sanctum中间件作为后卫,它是auth后卫的某种扩展,Laravel将其用作默认值,但会话由web中间件组处理。 / p>

我无法准确地表达一些内部的Laravel东西;目前,我比JavaScript更有经验。

在我的api.php文件中,我具有登录/注册/注销路径,在我的Kernel.php文件中,我将\Illuminate\Session\Middleware\StartSession::class,从Web组复制到了api组。

我必须这样做才能修复我的登录单元测试,该测试引发了有关“会话存储未按要求”的错误。复制使我的postJson请求可以在单元测试中工作,但是一段时间之后,我开始从JavaScript应用中看到419 CSRF错误发布(这很糟糕,因为它可以更早地工作)。

我开始在/storage/framework/sessions文件夹中追逐一些文件系统权限,但是问题不是(对我来说)。

我后来发现,使用Laravel Sanctum和默认的AuthenticatesUsers特征,您必须使用web保护进行身份验证,并使用auth:sanctum中间件来保护路由。我正在尝试对身份验证路由使用api防护,这对于我的419错误和AuthenticatesUsers特征是很重要的。

如果CSRF在工作或应该工作时有人得到419,我建议在系统中所有需要这些工作的关键点进行一些\Log::debug()调查:

Auth::check()

Auth::user()

Auth::logout()

根据我的观察,如果您的行为异常,则与sessions相关的配置有问题或与web相关的配置有问题,api守护者

防护措施与AuthManager防护措施有关,该防护措施在多个请求和多个单元测试中维持状态。

这是我发现的最好的描述,我花了一个多星期才发现:

Method Illuminate\Auth\RequestGuard::logout does not exist Laravel Passport

作为一个随机的最终示例,如果您的会话使用web中间件组中的数据以某种方式生成CSRF令牌,而您的路由设置为使用api,则它们可能会错误地解释接收到的CSRF。

此外,打开Chrome开发工具并转到“应用程序”标签,然后查看cookie。确保您的XSRF-TOKEN cookie不安全(即:不是httpOnly)。

这将使您拥有这样的Axios请求拦截器:

import Cookies from 'js-cookie';

axios.interceptors.request.use(async (request) => {
    try {
        const csrf = Cookies.get('XSRF-TOKEN');
        request.withCredentials = true;

        if (csrf) {
            request.headers.common['XSRF-TOKEN'] = csrf;
        }

        return request;
    } catch (err) {
        throw new Error(`axios# Problem with request during pre-flight phase: ${err}.`);
    }
});

这就是我当前的Laravel / Vue SPA成功运行的方式。

过去,我在这里也使用了这种技术:

app.blade.php (根布局文件,文档标题)

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

bootstrap.js (或任何位置)

window.axios = require('axios');

window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';

const token = document.head.querySelector('meta[name="csrf-token"]');

if (token) {
    window.axios.defaults.headers.common['X-CSRF-TOKEN'] = token.content;
} else {
    console.error('CSRF token not found: https://laravel.com/docs/csrf#csrf-x-csrf-token');
}

我认为,大多数问题将来自以下一个或多个文件中的错误值:

  • ./.env

  • ./config/auth.php

  • ./config/session.php

请密切注意SESSION_DOMAIN,SESSION_LIFETIME和SESSION_DRIVER等文件系统权限。

检查您的nginx access.log和/或error.log文件;它们可能包含提示。

答案 5 :(得分:0)

我遇到了同样的问题,但我的问题是 https。表单在 http 页面上,但操作在 https 上。结果导致session不同,导致csrf错误。

答案 6 :(得分:-3)

测试此代码

Route::get('/contact', [
   'uses' => 'ContactController@index',
   'nocsrf' => true,
]);
Route::post('/contact', [
   'uses' => 'ContactController@contactSubmit',
   'nocsrf' => true,
]);

或者您可以删除孔csrf

protected $except = [
    '*'
];