Laravel Sanctum XSRF-cookie-ТОКЕН не отправляется

#nuxtjs #laravel-sanctum

#nuxtjs #laravel-sanctum

Вопрос:

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

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

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

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

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

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' => AppHttpMiddlewareVerifyCsrfToken::class,
        'encrypt_cookies' => AppHttpMiddlewareEncryptCookies::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 IlluminateSupportStr;

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-ТОКЕНА не отправляется обратно?

Спасибо

Комментарии:

1. Пока нет ответов, можете ли вы поделиться дополнительной информацией? cors.php и session.php было бы полезно.

Ответ №1:

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

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

 axios: {
    credentials: true,
    baseURL: 'http://localhost/api/',
  },
 

Ответ №2:

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

Обратите внимание, что я не включил 'sanctum/csrf-cookie' в 'paths' , потому что я изменил префикс для Sanctum в sanctum.php . У меня также есть сервер разработки nuxt на порту 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' => AppHttpMiddlewareVerifyCsrfToken::class,
    'encrypt_cookies' => AppHttpMiddlewareEncryptCookies::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
 

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

Ответ №3:

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

Откройте файл Laravel .env и добавьте 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');
 

Ответ №4:

Возможно, ваше приложение laravel работает на 127.0.0.1: 8000, а ваш SPA работает на localhost: 3000 или localhost: 8080 и т.д.

Убедитесь, что вы:

  1. Установите для домена сеанса значение localhost
  2. Установите значение supports_credentials true (cors.php )
  3. Установите with_credentials значение true в вашем клиенте
  4. Когда вы отправляете запросы на свой серверный сервер, отправляйте его на localhost: 8000 вместо 127.0.0.1: 8000