我在同一台服务器上托管了多个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一起使用?
答案 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 = [
'*'
];