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






При тестировании аутентификации Sancum SPA через Postman обязательно включите заголовок Referer или Origin. Кроме того, убедитесь, что домен в предоставленном заголовке соответствует домену, указанному в значении конфигурации sanctum.stateful (например, домену, используемому вашей переменной APP_URL .env).
Эти условия необходимы промежуточному программному обеспечению statefulApi() для включения промежуточного программного обеспечения внешнего интерфейса (включая сеансы).
Вы можете увидеть код здесь для определения того, является ли это запросом внешнего интерфейса, который включает промежуточное программное обеспечение внешнего интерфейса.
Это отличный совет! Проверка исходного кода никогда раньше не приходила мне в голову. Это новая функция, представленная в Laravel 11? Раньше я не сталкивался с этой проблемой.
@henrbu Нет, это не ново, но способ включения промежуточного программного обеспечения святилища другой. В Laravel 11 вы используете вызов statefulApi(), чтобы включить его. В Laravel 10 и ниже вам приходилось вручную обновлять группу промежуточного программного обеспечения api, чтобы добавить промежуточное программное обеспечение EnsureFrontendRequestsAreStateful из Sanctum. Но в любом случае самому промежуточному программному обеспечению требуется заголовок «referer» или «origin» для запуска промежуточного программного обеспечения внешнего запроса (сеансов и т. д.).
Спасибо за объяснение, ценю! Я приму ответ, когда вернусь из поездки.
Патриций, я все еще сталкиваюсь с этой проблемой, даже если добавляю Referer или Origin в заголовки моего почтальона: localhost:5000. Есть предположения?
@henbru «localhost:5000» не включен в список доменов с отслеживанием состояния по умолчанию. На первый взгляд вы можете подумать, что он включен, потому что код выглядит так, будто он добавляет ваш APP_URL в список, но это не совсем так. Он запускает APP_URL (и FRONTEND_URL) посредством вызова parse_url() с флагом PHP_URL_HOST. Этот флаг не возвращает данные порта, поэтому результатом вызова будет просто «localhost», а не «localhost:5000». Измените заголовок Referer/Origin на «localhost:3000» (включен в список по умолчанию) и посмотрите, работает ли это.
Это вроде как помогло, но теперь выдает ошибку «Несоответствие токена CSRF», когда я добавляю Origin localhost:3000 в заголовки.
Похоже, что большая часть настроек была правильной, однако проблема возникла со стороны Postman. В основном следовал этому руководству, и все работало нормально youtube.com/watch?v=My61OicxPRO&ab_channel=cdruc
Попробуйте использовать: session()->regenerate()
В Laravel вспомогательная функция session() — это ярлык для доступа к экземпляру сеанса.
Экземпляр сеанса доступен глобально во всем приложении и обычно инициализируется в процессе начальной загрузки.
Действительно, это решило ошибку сеанса.
можно принять ответ?
Это решило часть проблемы, оба ответа не могут быть отмечены как принятые :(
Это также решило мою проблему. Спасибо!
laravel Sanctum - это аутентификация на основе токена, а не сеанса, переполнение для Sanctum довольно прямолинейно, вы пытаетесь войти в систему, как и после этого, вам нужно создать токен для этого пользователя, а затем вам нужно отправить его в качестве ответа на переднюю панель. конец, а затем из внешнего интерфейса вам нужно добавить его в заголовки со всеми запросами, которые будут добавлены в ваше промежуточное программное обеспечение святилища.