Laravel Sanctum XSRF-TOKEN Cookie 未发送

Laravel Sanctum XSRF-TOKEN Cookie not Getting Sent

我正在使用 Laravel 8,并且我一直在尝试遵循 SPA authentication 的密室文档。我已经完成设置所需的必要配置。后端服务器在具有默认端口 (80) 的本地主机上为 运行,而 SPA 客户端在 localhost:3000 上为 运行。我正在为带有 axios 的客户端使用 nuxt 框架来发出请求。

应向 /sanctum/csrf-cookie 发出初始请求以初始化 CSRF 保护 cookie,这是网络流量流量显示的内容

第二个请求是应该包含第一个域请求发送的 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/',
  },
}

有人能告诉我为什么 XSRF-TOKEN cookie 没有被发回吗?

谢谢

这是我的 Nuxt/Laravel 8/Sanctum 配置。

请注意,我没有在 'paths' 中包含 'sanctum/csrf-cookie',因为我在 sanctum.php 中更改了 Sanctum 的前缀。我还在端口 3050 上安装了我的 nuxt 开发服务器,这就是您将在我的配置中看到的内容。改变你的适合(例如 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 中的所有内容都是默认设置,但请确保使用正确的 SESSION_DOMAIN.

更新您的 .env
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 中的所有内容都是默认值,请确保在 .env 中输入正确的 SANCTUM_STATEFUL_DOMAIN(如下例)。我还添加了行 'prefix' => 'api'。这允许我在 axios 中设置单个 baseURL 并通过 http://localhost:3050/api/csrf-cookie 调用 csrf-cookie 路由。查看更多相关信息 here

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'

然后在前端,我用 baseURL 设置了 axios 并确保 withCredentials 设置为 true

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

假设您没有进行与上述设置相矛盾的其他更改,这应该有效:)

原来问题是由axios模块的nuxt配置引起的。我只是用 'credentials'.

替换了字段 'withCredentials'

这是更新后的 nuxt.config.js:

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

如果您按照这些指南进行操作但仍然遇到问题,就像我一样,您可能错过了 .env 文件中的设置 SESSION_DOMAIN

打开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');