Файл cookie Laravel Sanctum XSRF-TOKEN не отправляется

Я использую Laravel 8 и пытаюсь следовать документации Sanctum для Аутентификация SPA. Я уже выполнил настройку необходимых конфигураций. Внутренний сервер работает на локальном хосте с портом по умолчанию (80), в то время как клиент SPA работает на локальном хосте: 3000. Я использую фреймворк nuxt для клиента с axios, чтобы сделать запрос.

Первоначальный запрос должен быть сделан в / sanctum / csrf-cookie для инициализации файла cookie защиты CSRF, и вот какой сетевой трафик показывает

введите описание изображения здесь

Второй запрос - это фактический запрос, который должен содержать файлы cookie, отправленные первым запросом для домена, но похоже, что XSRF-TOKEN пропускается. Вот как выглядит сетевой трафик

введите описание изображения здесь

Конфигурационный файл sanctum.php:

<?php
return [
    'stateful' => explode(',', env(
        'SANCTUM_STATEFUL_DOMAINS',
        'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1'
    )),
    'expiration' => null,
    'middleware' => [
        'verify_csrf_token' => App\Http\Middleware\VerifyCsrfToken::class,
        'encrypt_cookies' => App\Http\Middleware\EncryptCookies::class,
    ],
];

Файл конфигурации cors.php:

<?php
return [
    'paths' => ['api/*', 'sanctum/csrf-cookie'],
    'allowed_methods' => ['*'],
    'allowed_origins' => ['*', 'localhost:3000'],
    'allowed_origins_patterns' => [],
    'allowed_headers' => ['*'],
    'exposed_headers' => ['XSRF-TOKEN', 'X-XSRF-TOKEN'],
    'max_age' => 0,
    'supports_credentials' => true,
];

файл конфигурации session.php

<?php

use Illuminate\Support\Str;

return [
    'driver' => env('SESSION_DRIVER', 'file'),
    'lifetime' => env('SESSION_LIFETIME', 120),
    'expire_on_close' => false,
    'encrypt' => false,
    'files' => storage_path('framework/sessions'),
    'connection' => env('SESSION_CONNECTION', null),
    'table' => 'sessions',
    'store' => env('SESSION_STORE', null),
    'lottery' => [2, 100],
    'cookie' => env(
        'SESSION_COOKIE',
        Str::slug(env('APP_NAME', 'laravel'), '_').'_session'
    ),
    'path' => '/',
    'domain' => env('SESSION_DOMAIN', null),
    'secure' => env('SESSION_SECURE_COOKIE'),
    'http_only' => true,
    'same_site' => 'lax',
];

Я установил это в nuxt.config.js

export default {
  axios: {
    withCredentials: true,
    baseURL: 'http://localhost/',
  },
}

Может кто-нибудь сказать мне, почему файл cookie XSRF-TOKEN не отправляется обратно?

Спасибо


person Michael Erwin    schedule 28.12.2020    source источник
comment
Пока нет ответов, не могли бы вы поделиться дополнительной информацией? cors.php и session.php были бы полезны.   -  person Nick Dawes    schedule 30.12.2020
comment
@NickDawes Сейчас обновлено.   -  person Michael Erwin    schedule 30.12.2020


Ответы (3)


Оказывается, проблема была вызвана конфигурацией nuxt для модуля axios. Я просто заменил поле withCredentials на просто credentials.

Теперь это обновленный nuxt.config.js:

axios: {
    credentials: true,
    baseURL: 'http://localhost/api/',
  },
person Michael Erwin    schedule 30.12.2020

Вот моя конфигурация Nuxt / Laravel 8 / Sanctum.

Заметьте, я не включил 'sanctum/csrf-cookie' в 'paths', потому что я изменил префикс для Sanctum в sanctum.php. У меня также есть сервер nuxt dev на порту 3050, это то, что вы увидите в моей конфигурации. Измените свой на подходящий (например, 3000).

cors.php

'paths' => ['api/*'],
'allowed_methods' => ['*'],
'allowed_origins' => [env('ALLOWED_ORIGINS')], 
    .env e.g.: ALLOWED_ORIGINS=http://localhost:3050
'allowed_origins_patterns' => [],
'allowed_headers' => ['*'],
'exposed_headers' => [],
'max_age' => 0,
'supports_credentials' => true,

Все в session.php оставлено по умолчанию, но убедитесь, что вы обновили свой .env правильным SESSION_DOMAIN.

session.php

'driver' => env('SESSION_DRIVER', 'file'),
'lifetime' => env('SESSION_LIFETIME', 120),
'expire_on_close' => false,
'encrypt' => false,
'files' => storage_path('framework/sessions'),
'connection' => env('SESSION_CONNECTION', null),
'table' => 'sessions',
'store' => env('SESSION_STORE', null),
'lottery' => [2, 100],
'cookie' => env(
    'SESSION_COOKIE',
    Str::slug(env('APP_NAME', 'laravel'), '_').'_session'
),
'path' => '/',
'domain' => env('SESSION_DOMAIN', null),
    .env e.g.: SESSION_DOMAIN=localhost
'secure' => env('SESSION_SECURE_COOKIE'),
'http_only' => true,
'same_site' => 'lax',

Все в sanctum.php по умолчанию, убедитесь, что вы ввели правильный SANCTUM_STATEFUL_DOMAIN в свой .env (пример ниже). Я также добавил строку 'prefix' => 'api'. Это позволяет мне установить один baseURL в axios и вызвать маршрут csrf-cookie через http://localhost:3050/api/csrf-cookie. Подробнее об этом можно узнать здесь.

sanctum.php

'stateful' => explode(',', env(
    'SANCTUM_STATEFUL_DOMAINS',
        .env e.g.: SANCTUM_STATEFUL_DOMAINS=localhost:3050
    'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1'
)),
'expiration' => null,
'middleware' => [
    'verify_csrf_token' => App\Http\Middleware\VerifyCsrfToken::class,
    'encrypt_cookies' => App\Http\Middleware\EncryptCookies::class,
],
'prefix' => 'api'

Затем на интерфейсе я установил axios с помощью baseURL и убедился, что для withCredentials установлено значение true.

axios.defaults.withCredentials = true;
axios.defaults.baseURL = process.env.API_BASE_URL;
    .env e.g.: API_BASE_URL=http://localhost:8000/api

Предполагая, что вы не внесли никаких других изменений, противоречащих вышеуказанным настройкам, это должно сработать :)

person Nick Dawes    schedule 30.12.2020

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

Откройте файл .env Laravel и добавьте SESSION_DOMAIN=.localhost

Еще одна вещь: если вы по какой-то причине не можете получить доступ к маршруту / csrf-cookie и по-прежнему необходимо вызвать sanctum / csrf-cookie /, но Axios добавляет /api перед вашими запросами, используйте этот фрагмент кода:

let myNewInstance = this.$axios.create({
   baseURL: 'http://localhost' //without /api at the end
});

myNewInstance.get('/sanctum/csrf-cookie');
person Svetoslav Stefanov    schedule 16.04.2021