Хранилище сеансов не установлено по запросу Laravel 11

Я пытаюсь реализовать базовую функцию аутентификации в целях тестирования. Я тестирую через Postman, поэтому перед входом в систему я делаю GET-запрос на /sanctum/csrf-cookie. После этого я попадаю в конечную точку /login и могу получать данные (если эта часть $request->session()->regenerate(); закомментирована). Однако если я попытаюсь получить доступ к защищенному маршруту, я получаю сообщение об ошибке. Несмотря на внимательное изучение документации, я столкнулся с проблемой, когда пользователь пытается войти в систему. Я получаю сообщение об ошибке, когда $request->session()->regenerate(); это не закомментировано:

"message": "Session store not set on request."

Вот мой bootstrap/app.php:

return Application::configure(basePath: dirname(__DIR__))
    ->withRouting(
        using: function () {
            Route::middleware('api')
                ->prefix('api')
                ->group(function () {
                    // routes/api.php is not included here
                    require base_path('routes/Api/V1/Auth/routes.php');
                });
        },
        web: __DIR__ . '/../routes/web.php',
        commands: __DIR__ . '/../routes/console.php',
        health: '/up',
    )
    ->withMiddleware(function (Middleware $middleware) {
        $middleware->statefulApi();
    })
    ->withExceptions(function (Exceptions $exceptions) {
        //
    })->create();

Вот мой логин:

public function login(object $request)
    {
        // Validate user credentials
        if (!Auth::attempt($request->only(['username', 'password']))) {
            return $this->failedRequest('', 'Invalid email address or password', 400);
        }

        // Regenerate the user's session to prevent session fixation
        $request->session()->regenerate();

        // Sign in user
        Auth::login(Auth::user());

        // Return data
        return $this->successfullRequest(Auth::user(), 'User successfully logged in', 200);
    }

Мои маршруты:

Route::group(['prefix' => 'v1/auth'], function () {
    Route::post('register', [AuthController::class, 'register']);
    Route::post('login', [AuthController::class, 'login']);
    Route::post('logout', [AuthController::class, 'logout'])->middleware('auth:sanctum');
});

Если я удалю эту часть, я в основном получаю сообщение «Неаутентифицировано», когда пытаюсь нажать .../выход из системы.

$request->session()->regenerate();

Sancum.php -> с сохранением состояния:

'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf(
        '%s%s%s',
        'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1',
        env('APP_URL') ? ',' . parse_url(env('APP_URL'), PHP_URL_HOST) : '',
        env('FRONTEND_URL') ? ',' . parse_url(env('FRONTEND_URL'), PHP_URL_HOST) : ''))),

мой env-файл:

APP_URL=http://localhost:5000
FRONTEND_URL=http://localhost:3000

laravel Sanctum - это аутентификация на основе токена, а не сеанса, переполнение для Sanctum довольно прямолинейно, вы пытаетесь войти в систему, как и после этого, вам нужно создать токен для этого пользователя, а затем вам нужно отправить его в качестве ответа на переднюю панель. конец, а затем из внешнего интерфейса вам нужно добавить его в заголовки со всеми запросами, которые будут добавлены в ваше промежуточное программное обеспечение святилища.

Harris 29.03.2024 17:12

@Харрис, ты уверен? «Для этой функции Sanctum не использует никаких токенов. Вместо этого Sanctum использует встроенные службы аутентификации сеансов Laravel на основе файлов cookie». laravel.com/docs/11.x/sanctum#spa-authentication

henrbu 29.03.2024 17:53
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Поиск нового уровня в Laravel с помощью MeiliSearch и Scout
Поиск нового уровня в Laravel с помощью MeiliSearch и Scout
Laravel Scout - это популярный пакет, который предоставляет простой и удобный способ добавить полнотекстовый поиск в ваше приложение Laravel. Он...
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
В последние годы архитектура микросервисов приобрела популярность как способ построения масштабируемых и гибких приложений. Laravel , популярный PHP...
Как построить CRUD-приложение в Laravel
Как построить CRUD-приложение в Laravel
Laravel - это популярный PHP-фреймворк, который позволяет быстро и легко создавать веб-приложения. Одной из наиболее распространенных задач в...
1
2
2 044
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

При тестировании аутентификации Sancum SPA через Postman обязательно включите заголовок Referer или Origin. Кроме того, убедитесь, что домен в предоставленном заголовке соответствует домену, указанному в значении конфигурации sanctum.stateful (например, домену, используемому вашей переменной APP_URL .env).

Эти условия необходимы промежуточному программному обеспечению statefulApi() для включения промежуточного программного обеспечения внешнего интерфейса (включая сеансы).

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

Это отличный совет! Проверка исходного кода никогда раньше не приходила мне в голову. Это новая функция, представленная в Laravel 11? Раньше я не сталкивался с этой проблемой.

henrbu 02.04.2024 17:46

@henrbu Нет, это не ново, но способ включения промежуточного программного обеспечения святилища другой. В Laravel 11 вы используете вызов statefulApi(), чтобы включить его. В Laravel 10 и ниже вам приходилось вручную обновлять группу промежуточного программного обеспечения api, чтобы добавить промежуточное программное обеспечение EnsureFrontendRequestsAreStateful из Sanctum. Но в любом случае самому промежуточному программному обеспечению требуется заголовок «referer» или «origin» для запуска промежуточного программного обеспечения внешнего запроса (сеансов и т. д.).

patricus 03.04.2024 02:07

Спасибо за объяснение, ценю! Я приму ответ, когда вернусь из поездки.

henrbu 03.04.2024 11:45

Патриций, я все еще сталкиваюсь с этой проблемой, даже если добавляю Referer или Origin в заголовки моего почтальона: localhost:5000. Есть предположения?

henrbu 06.04.2024 17:06

@henbru «localhost:5000» не включен в список доменов с отслеживанием состояния по умолчанию. На первый взгляд вы можете подумать, что он включен, потому что код выглядит так, будто он добавляет ваш APP_URL в список, но это не совсем так. Он запускает APP_URLFRONTEND_URL) посредством вызова parse_url() с флагом PHP_URL_HOST. Этот флаг не возвращает данные порта, поэтому результатом вызова будет просто «localhost», а не «localhost:5000». Измените заголовок Referer/Origin на «localhost:3000» (включен в список по умолчанию) и посмотрите, работает ли это.

patricus 09.04.2024 00:46

Это вроде как помогло, но теперь выдает ошибку «Несоответствие токена CSRF», когда я добавляю Origin localhost:3000 в заголовки.

henrbu 20.04.2024 16:24

Похоже, что большая часть настроек была правильной, однако проблема возникла со стороны Postman. В основном следовал этому руководству, и все работало нормально youtube.com/watch?v=My61OicxPRO&ab_channel=cdruc

henrbu 22.04.2024 16:44

Попробуйте использовать: session()->regenerate()

В Laravel вспомогательная функция session() — это ярлык для доступа к экземпляру сеанса.

Экземпляр сеанса доступен глобально во всем приложении и обычно инициализируется в процессе начальной загрузки.

Действительно, это решило ошибку сеанса.

henrbu 22.04.2024 16:44

можно принять ответ?

Ismoil Shifoev 23.04.2024 06:21

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

henrbu 23.04.2024 15:33

Это также решило мою проблему. Спасибо!

mackth 09.07.2024 15:18

Другие вопросы по теме