Ошибка Laravel 419 - проблема VerifyCsrfToken

У меня есть несколько сайтов Laravel, размещенных на одном сервере. С последним сайтом, который я создал, контактная форма отказывается отправить, не выдавая ошибку 419. Я настроил маршрутизацию в своем файле web.php, как и на других веб-сайтах, на которых есть действующие рабочие контактные формы, и я генерирую и отправляю токен точно так же, {{ csrf_field() }},

Я нашел ответ на аналогичный вопрос о том, что вы можете отключить проверку Csrf, добавив записи в $except массив в app/Http/Middleware/VerifyCsrfToken.php, Я проверил, что это действительно разрешает ошибку 419:

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

Но, конечно, я хочу сохранить функциональность Csrf, и я только обновил $except массив для устранения неисправностей.

Кто-нибудь знает, что может отличаться в новой среде Laravel, которая будет иметь такое поведение 419, несмотря на передачу сгенерированного токена? Я пытался обновить ряд настроек ENV и переключать разные вещи, но ничего кроме изменения $except Массив оказал какое-либо влияние на проблему.

Обновить

Поскольку до сих пор было небольшое обсуждение, я решил предоставить дополнительную информацию и код.

Во-первых, это форма Ajax, но пока не выпрыгивайте со своего места. Я тестировал форму как с, так и без ajax. Если я хочу протестировать с ajax, я просто нажимаю кнопку, подключенную к слушателю jQuery. Если нет, я изменяю или удаляю идентификатор кнопки, или запускаю $("#formName").submit(); в окне консоли.

Выше (ajax, старомодный способ отправки и селектор jquery с .submit();) все приводят к одному и тому же ответу - ошибка 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?

9 ответов

TL; DR: этот пост содержит множество потенциальных проблем и исправлений; он предназначен для тех, кто ищет соответствующую бонусную информацию, когда застревает.

Я только что столкнулся с этой ошибкой, используя Laravel Sanctum в том, что выглядит как неправильно настроенное промежуточное ПО. Sanctum используетauth:sanctum промежуточное ПО для сторожа, которое является своего рода расширением auth Guard, который Laravel использует по умолчанию, но сеанс обрабатывается web группа промежуточного программного обеспечения.

Я не могу точно выразить словами некоторые из этих внутренних вещей Laravel; На данный момент у меня больше опыта с JavaScript, чем с PHP.

В моем api.php файла, у меня были маршруты входа / регистрации / выхода, а в моем Kernel.php файл, я скопировал \Illuminate\Session\Middleware\StartSession::class, из веб-группы в группу api.

Мне пришлось сделать это, чтобы исправить мой модульный тест входа в систему, который выдавал ошибку "Хранилище сеансов не по запросу". Копирование, которое позволило мнеpostJson запрос на работу в модульном тесте, но через некоторое время я начал видеть сообщение об ошибке 419 CSRF из приложения JavaScript (что плохо, потому что раньше оно работало нормально).

Я начал преследовать некоторые отвлекающие маневры разрешения файловой системы в /storage/framework/sessions папка, но проблема была не в этом (для меня).

Позже я выяснил, что с Laravel Sanctum и по умолчанию AuthenticatesUsers черта, вы должны использовать web охранник для авторизации, а auth:sanctumпромежуточное ПО для защищенных маршрутов. Я пытался использоватьapi защита для маршрутов аутентификации, и это было центральным элементом моих 419 ошибок с чертой AuthenticatesUsers.

Если кто-то получит 419, пока CSRF работал или должен работать, я рекомендую сделать несколько \Log::debug() исследования во всех ключевых точках вашей системы, где они вам нужны:

Auth::check()

Auth::user()

Auth::logout()

Если вы наблюдаете странное поведение с ними, по моим наблюдениям, что-то не так с вашей конфигурацией, связанной с sessions или что-то не так с вашей конфигурацией, связанной с web, api охранники.

Охранники имеют отношение к AuthManager guard, который поддерживает состояние нескольких запросов и нескольких модульных тестов.

Это лучшее описание, которое я нашел, на изучение которого у меня ушла больше недели:

Метод Illuminate\Auth\RequestGuard::logout не существует Laravel Passport

В качестве случайного последнего примера, если ваш сеанс каким-то образом генерирует токен CSRF, используя данные из web группа промежуточного программного обеспечения, пока ваши маршруты настроены на использование 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файл; они могут содержать намек.

Возможно, ваш домен в адресной строке браузера не совпадает domain ключ в config/session.php config или SESSION_DOMAIN в вашем файле env.

Только что нашел вашу проблему в рамках репо. Это не проблема laravel, в вашей установке отсутствуют права на запись в папку хранилища, поэтому laravel не может записывать сеанс, журналы и т. Д.

Вы получаете ошибку 419, потому что вы не можете записать в файлы, таким образом, вы не можете создать сессию n, поэтому вы не можете проверить токен csrf.

Быстрая починка: chmod -R 777 storage

Правильное исправление: переместите вашу установку в папку, в которую nginx/apache/ ваш пользователь может написать. Если вы используете nginx/apache, перенесите туда свое приложение и предоставьте необходимые права на проект (chown -R www-data: /path-to-project)Если вы используете php artisan serve, измените его разрешения для вашего пользователя: chown -R $(whoami) /path-to-project

Вы понимаете, пусть писатели пишут, и у вас все хорошо.

У меня была такая же проблема, но в моем случае проблема была в https. Форма была на http-странице, но действие было на https. В результате сеанс отличается, что вызывает ошибку csrf.

Я использовал одно и то же имя приложения для staging и prod, будучи поддоменом prod. После изменения имени приложения в постановке это сработало

У нас была эта проблема, оказалось, что нашsessionstable не соответствовал используемой нами версии Laravel. Я бы порекомендовал посмотреть, заполняется ли он или остается пустым (как у нас).

Если он пуст, даже если у вас есть люди, посещающие сайт, я бы сказал, что проблема именно в этом.

(Если вы не используете базу данных для хранения своих сеансов , очевидно, я бы предложил вместо этого проверять, где бы вы ни находились.)

Ознакомьтесь с моим ответом на этот вопрос, поможет ли он в том, чего вы пытаетесь достичь. Ошибка возврата запроса на отправку формы 419 unknown status laravel

Запустите эту команду php artisan key:generate

Проверить этот код

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

или вы можете удалить отверстие CSRF

protected $except = [
    '*'
];
Другие вопросы по тегам