Почему не работает путь /sanctum/csrf-cookie?
Всем привет, в общем у меня есть проект на laravel/nuxt js 3, сделал авторизацию с csrf - локально всё ок работает
api.php
Route::middleware('auth:sanctum')->group(function () { // Защищенные маршруты Route::get('/all_languages', [LanguageController::class, 'index']); Route::delete('/language_delete/{id}', [LanguageController::class, 'destroy']); Route::post('/languages_add', [LanguageController::class, 'store']); Route::get('/all_sections', [SectionController::class, 'index']); Route::delete('/section_delete/{id}', [SectionController::class, 'destroy']); Route::post('/section_add', [SectionController::class, 'store']); Route::post('/logout', [AuthController::class, 'logout']); Route::get('/exercises', [ExerciseController::class, 'getThemes']); Route::post('/exercises_create', [ExerciseController::class, 'create']); Route::get('/exercises_check_theme', [ExerciseController::class, 'checkIfThemeExists']); Route::get('/get-exercises', [ExerciseController::class, 'getExercises']); Route::post('/add-exercise', [ExerciseController::class, 'addExercise']); Route::post('/delete-exercises', [ExerciseController::class, 'deleteExercises']); Route::post('/delete-task-exercise', [ExerciseController::class, 'deleteTaskExercise']); Route::post('/upload-video', [VideoUploadController::class, 'upload']); Route::post('/upload-image', [ImageUploadController::class, 'upload']); Route::post('/upload-audio', [AudioUploadController::class, 'upload']); Route::put('/update-exercise', [ExerciseController::class, 'updateExercise']); }); Route::post('register', [AuthController::class, 'register']); Route::post('/login', [AuthController::class, 'login']); |
Route::middleware('auth:sanctum')->group(function () { // Защищенные маршруты Route::get('/all_languages', [LanguageController::class, 'index']); Route::delete('/language_delete/{id}', [LanguageController::class, 'destroy']); Route::post('/languages_add', [LanguageController::class, 'store']); Route::get('/all_sections', [SectionController::class, 'index']); Route::delete('/section_delete/{id}', [SectionController::class, 'destroy']); Route::post('/section_add', [SectionController::class, 'store']); Route::post('/logout', [AuthController::class, 'logout']); Route::get('/exercises', [ExerciseController::class, 'getThemes']); Route::post('/exercises_create', [ExerciseController::class, 'create']); Route::get('/exercises_check_theme', [ExerciseController::class, 'checkIfThemeExists']); Route::get('/get-exercises', [ExerciseController::class, 'getExercises']); Route::post('/add-exercise', [ExerciseController::class, 'addExercise']); Route::post('/delete-exercises', [ExerciseController::class, 'deleteExercises']); Route::post('/delete-task-exercise', [ExerciseController::class, 'deleteTaskExercise']); Route::post('/upload-video', [VideoUploadController::class, 'upload']); Route::post('/upload-image', [ImageUploadController::class, 'upload']); Route::post('/upload-audio', [AudioUploadController::class, 'upload']); Route::put('/update-exercise', [ExerciseController::class, 'updateExercise']); }); Route::post('register', [AuthController::class, 'register']); Route::post('/login', [AuthController::class, 'login']);
AuthController.php
// Метод для авторизации public function login(Request $request) { $credentials = $request->only('name', 'password'); $user = User::where('name', $credentials['name'])->first(); if (!$user) { return response()->json(['message' => 'Пользователь не существует'], 404); } if (!Hash::check($credentials['password'], $user->password)) { return response()->json(['message' => 'Неверный пароль'], 401); } if (Auth::attempt($credentials)) { $user = Auth::user(); // Создание токена $token = $user->createToken('authToken')->plainTextToken; // Разделение токена на две части [$id, $token] = explode('|', $token, 2); // Установка HttpOnly куки с токеном $cookie = cookie('auth_token', $token, 525600); // Установка куки на 60 минут // Возвращаем ответ с установленной кукой return response()->json([ 'message' => 'Авторизация успешна', 'user' => $user, ])->withCookie($cookie); } return response()->json(['message' => 'Неверный логин или пароль'], 401); } |
// Метод для авторизации public function login(Request $request) { $credentials = $request->only('name', 'password'); $user = User::where('name', $credentials['name'])->first(); if (!$user) { return response()->json(['message' => 'Пользователь не существует'], 404); } if (!Hash::check($credentials['password'], $user->password)) { return response()->json(['message' => 'Неверный пароль'], 401); } if (Auth::attempt($credentials)) { $user = Auth::user(); // Создание токена $token = $user->createToken('authToken')->plainTextToken; // Разделение токена на две части [$id, $token] = explode('|', $token, 2); // Установка HttpOnly куки с токеном $cookie = cookie('auth_token', $token, 525600); // Установка куки на 60 минут // Возвращаем ответ с установленной кукой return response()->json([ 'message' => 'Авторизация успешна', 'user' => $user, ])->withCookie($cookie); } return response()->json(['message' => 'Неверный логин или пароль'], 401); }
cors.php
'paths' => ['api/*', 'sanctum/csrf-cookie'], 'allowed_methods' => ['*'], 'allowed_origins' => ['*'], 'allowed_origins_patterns' => [], 'allowed_headers' => ['*'], 'exposed_headers' => [], 'max_age' => 0, 'supports_credentials' => true |
'paths' => ['api/*', 'sanctum/csrf-cookie'], 'allowed_methods' => ['*'], 'allowed_origins' => ['*'], 'allowed_origins_patterns' => [], 'allowed_headers' => ['*'], 'exposed_headers' => [], 'max_age' => 0, 'supports_credentials' => true
sanctum.php
'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf( '%s%s', 'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1', Sanctum::currentApplicationUrlWithPort() ))), |
'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf( '%s%s', 'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1', Sanctum::currentApplicationUrlWithPort() ))),
utils/getBaseUrl.js
export function getBaseUrl() { const requestUrl = useRequestURL(); const protocol = requestUrl.protocol; // 'http:' or'https:' const host = requestUrl.hostname; // 'localhost' or sharpsss.ru // const port = requestUrl.port ? `:${requestUrl.port}` : ''; // port //return `${protocol}//${host}:8000`; //localhost return `${protocol}//${host}`; //sharpsss.ru prod } |
export function getBaseUrl() { const requestUrl = useRequestURL(); const protocol = requestUrl.protocol; // 'http:' or'https:' const host = requestUrl.hostname; // 'localhost' or sharpsss.ru // const port = requestUrl.port ? `:${requestUrl.port}` : ''; // port //return `${protocol}//${host}:8000`; //localhost return `${protocol}//${host}`; //sharpsss.ru prod }
utils/utils.js
// utils.js import { getBaseUrl } from "~/utils/getBaseUrl.js" export async function fetchCsrfToken() { const baseUrl = getBaseUrl(); await $fetch(`${baseUrl}/sanctum/csrf-cookie`, { method: 'GET', credentials: 'include', }); } |
// utils.js import { getBaseUrl } from "~/utils/getBaseUrl.js" export async function fetchCsrfToken() { const baseUrl = getBaseUrl(); await $fetch(`${baseUrl}/sanctum/csrf-cookie`, { method: 'GET', credentials: 'include', }); }
Admin.vue тут метод авторизации
async function login() { // const config = useRuntimeConfig(); if (!loginData.value.name || !loginData.value.password) { showError.value = true; errorMessage.value = "Пожалуйста, заполните все поля."; return; } try { // Получение CSRF токена await fetchCsrfToken(); // Отправка запроса на авторизацию const baseUrl = getBaseUrl(); const response = await $fetch(`${baseUrl}/api/login`, { method: 'POST', credentials: 'include', headers: { 'X-XSRF-TOKEN': decodeURIComponent(getCookie('XSRF-TOKEN')), 'Accept': 'application/json, text/plain, */*', 'Content-Type': 'application/json', 'X-Requested-With': 'XMLHttpRequest', }, body: loginData.value, // Теперь мы передаем объект напрямую }); // Проверка успешной авторизации if (response && response.message === 'Авторизация успешна') { router.push('/content/Admin_panel'); authStore.setAuthentication(true); // Устанавливаем аутентификацию в true // Установить состояние аутентификации при успешном входе localStorage.setItem('isAuthenticated', '1'); // console.log("Аутентификация прошла успешно"); } } catch (error) { if (error.response) { switch (error.response.status) { case 401: errorMessage.value = "Неверный пароль"; break; case 404: errorMessage.value = "Пользователь не существует"; break; default: errorMessage.value = "Произошла ошибка аутентификации"; } } else { errorMessage.value = "Ошибка соединения с сервером"; } showError.value = true; } } |
async function login() { // const config = useRuntimeConfig(); if (!loginData.value.name || !loginData.value.password) { showError.value = true; errorMessage.value = "Пожалуйста, заполните все поля."; return; } try { // Получение CSRF токена await fetchCsrfToken(); // Отправка запроса на авторизацию const baseUrl = getBaseUrl(); const response = await $fetch(`${baseUrl}/api/login`, { method: 'POST', credentials: 'include', headers: { 'X-XSRF-TOKEN': decodeURIComponent(getCookie('XSRF-TOKEN')), 'Accept': 'application/json, text/plain, */*', 'Content-Type': 'application/json', 'X-Requested-With': 'XMLHttpRequest', }, body: loginData.value, // Теперь мы передаем объект напрямую }); // Проверка успешной авторизации if (response && response.message === 'Авторизация успешна') { router.push('/content/Admin_panel'); authStore.setAuthentication(true); // Устанавливаем аутентификацию в true // Установить состояние аутентификации при успешном входе localStorage.setItem('isAuthenticated', '1'); // console.log("Аутентификация прошла успешно"); } } catch (error) { if (error.response) { switch (error.response.status) { case 401: errorMessage.value = "Неверный пароль"; break; case 404: errorMessage.value = "Пользователь не существует"; break; default: errorMessage.value = "Произошла ошибка аутентификации"; } } else { errorMessage.value = "Ошибка соединения с сервером"; } showError.value = true; } }
app/http/Kernel.php
protected $middlewareGroups = [ 'web' => [ AppHttpMiddlewareEncryptCookies::class, IlluminateCookieMiddlewareAddQueuedCookiesToResponse::class, IlluminateSessionMiddlewareStartSession::class, IlluminateViewMiddlewareShareErrorsFromSession::class, AppHttpMiddlewareVerifyCsrfToken::class, IlluminateRoutingMiddlewareSubstituteBindings::class, ], 'api' => [ LaravelSanctumHttpMiddlewareEnsureFrontendRequestsAreStateful::class, IlluminateRoutingMiddlewareThrottleRequests::class.':api', IlluminateRoutingMiddlewareSubstituteBindings::class, ], ]; |
protected $middlewareGroups = [ 'web' => [ AppHttpMiddlewareEncryptCookies::class, IlluminateCookieMiddlewareAddQueuedCookiesToResponse::class, IlluminateSessionMiddlewareStartSession::class, IlluminateViewMiddlewareShareErrorsFromSession::class, AppHttpMiddlewareVerifyCsrfToken::class, IlluminateRoutingMiddlewareSubstituteBindings::class, ], 'api' => [ LaravelSanctumHttpMiddlewareEnsureFrontendRequestsAreStateful::class, IlluminateRoutingMiddlewareThrottleRequests::class.':api', IlluminateRoutingMiddlewareSubstituteBindings::class, ], ];
заливаю на прод с такой вот конфигурацией nginx
nginx config
server { listen 80; listen [::]:80; server_name sharpsss.ru www.sharpsss.ru; return 301 https://$host$request_uri; } server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name sharpsss.ru www.sharpsss.ru; ssl_certificate /etc/letsencrypt/live/sharpsss.ru/fullchain.pem; # managed by Certbot ssl_certificate_key /etc/letsencrypt/live/sharpsss.ru/privkey.pem; # managed by Certbot root /var/www/cms_prod/app_api/public; index index.php index.html index.htm; #Laravel API и Sanctum CSRF Cookie # location ^~ /api/sanctum/csrf-cookie/ { # try_files $uri $uri/ /index.php$is_args$args; # } location ^~ /sanctum/csrf-cookie/ { try_files $uri $uri/ /index.php$is_args$args; } location ^~ /api/ { try_files $uri $uri/ /index.php$is_args$args; } # Обрабатывать PHP скрипты location ~ .php$ { include snippets/fastcgi-php.conf; fastcgi_pass unix:/run/php/php8.2-fpm.sock; } # Все остальные запросы перенаправлять на Nuxt.js сервер location / { proxy_pass http://localhost:3000; # Используйте localhost, если Nuxt.js запущен на том же сервере proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_cache_bypass $http_upgrade; } # Дополнительные настройки SSL # ... } |
server { listen 80; listen [::]:80; server_name sharpsss.ru www.sharpsss.ru; return 301 https://$host$request_uri; } server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name sharpsss.ru www.sharpsss.ru; ssl_certificate /etc/letsencrypt/live/sharpsss.ru/fullchain.pem; # managed by Certbot ssl_certificate_key /etc/letsencrypt/live/sharpsss.ru/privkey.pem; # managed by Certbot root /var/www/cms_prod/app_api/public; index index.php index.html index.htm; #Laravel API и Sanctum CSRF Cookie # location ^~ /api/sanctum/csrf-cookie/ { # try_files $uri $uri/ /index.php$is_args$args; # } location ^~ /sanctum/csrf-cookie/ { try_files $uri $uri/ /index.php$is_args$args; } location ^~ /api/ { try_files $uri $uri/ /index.php$is_args$args; } # Обрабатывать PHP скрипты location ~ .php$ { include snippets/fastcgi-php.conf; fastcgi_pass unix:/run/php/php8.2-fpm.sock; } # Все остальные запросы перенаправлять на Nuxt.js сервер location / { proxy_pass http://localhost:3000; # Используйте localhost, если Nuxt.js запущен на том же сервере proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_cache_bypass $http_upgrade; } # Дополнительные настройки SSL # ... }
выдаёт ошибку при https://sharpsss.ru/sanctum/csrf-cookie
Request URL: https://sharpsss.ru/sanctum/csrf-cookie Request Method: GET Status Code: 404 Not Found Remote Address: 134.0.117.3:443 Referrer Policy: strict-origin-when-cross-origin |
Request URL: https://sharpsss.ru/sanctum/csrf-cookie Request Method: GET Status Code: 404 Not Found Remote Address: 134.0.117.3:443 Referrer Policy: strict-origin-when-cross-origin
пробовал в .env ставить SESSION_SECURE_COOKIE=true,также пробовал prefix в api/config/sanctum.php 'prefix' => 'api/sanctum' ставить чтобы по api/santum отрабатывало (и чисто получение вроде как работало но лишь при авторизации потом все мидлвар запросы не работали) почему то ссылку не даёт крепить
также пробовал в app.php в 'providers' добавлять LaravelSanctumSanctumServiceProvider::class,не помогло, в роут листе гет вот так обозначен
GET|HEAD sanctum/csrf-cookie .......................................................... sanctum.csrf-cookie › LaravelSanctum › CsrfCookieController@show |
GET|HEAD sanctum/csrf-cookie .......................................................... sanctum.csrf-cookie › LaravelSanctum › CsrfCookieController@show
Дополнительно:
1. А что у вас слушает 8000 порт, если у вас nginx слушает 80 и 443?
2. Зачем пробрасывать каждый урл - если стандартно принято пробрасывать все что не найдено - на index.php?
выдаёт ошибку (failed)net::ERR_CONNECTION_REFUSED при запросе https://sharpsss.ru/sanctum/csrf-cookie
а при https://sharpsss.ru/sanctum/csrf-cookie выдаёт
Для того что бы отвечать на вопросы - надо понимать что у вас там вообще происходит. Потому что причин по которым может происходит то или иное может быть миллиард. Вот это https://sharpsss.ru/sanctum/csrf-cookie это так у вас nginx 404 или это ларка такой 404 отдает?
location /sanctum/csrf-cookie { } |
location /sanctum/csrf-cookie { }
не работает? а если тупо погасить nuxt - 502 получим?
server { listen 80; listen [::]:80; server_name sharpsss.ru www.sharpsss.ru; return 301 https://$host$request_uri; } server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name sharpsss.ru www.sharpsss.ru; ssl_certificate /etc/letsencrypt/live/sharpsss.ru/fullchain.pem; # managed by Certbot ssl_certificate_key /etc/letsencrypt/live/sharpsss.ru/privkey.pem; # managed by Certbot # Указываем корневой каталог для Laravel root /var/www/cms_prod/app_api/public; index index.php index.html index.htm; # Для PHP location ~ .php$ { include snippets/fastcgi-php.conf; fastcgi_pass unix:/run/php/php8.2-fpm.sock; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } # Перенаправляем все запросы на front controller Laravel location / { try_files $uri $uri/ /index.php?$query_string; } } |
server { listen 80; listen [::]:80; server_name sharpsss.ru www.sharpsss.ru; return 301 https://$host$request_uri; } server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name sharpsss.ru www.sharpsss.ru; ssl_certificate /etc/letsencrypt/live/sharpsss.ru/fullchain.pem; # managed by Certbot ssl_certificate_key /etc/letsencrypt/live/sharpsss.ru/privkey.pem; # managed by Certbot # Указываем корневой каталог для Laravel root /var/www/cms_prod/app_api/public; index index.php index.html index.htm; # Для PHP location ~ .php$ { include snippets/fastcgi-php.conf; fastcgi_pass unix:/run/php/php8.2-fpm.sock; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } # Перенаправляем все запросы на front controller Laravel location / { try_files $uri $uri/ /index.php?$query_string; } }
Job for nginx.service failed because the control process exited with error code.
See "systemctl status nginx.service" and "journalctl -xeu nginx.service" for details.
include /etc/nginx/sites-enabled/*; которая означает подключи все что найдешь
у вас судя повсему где то гвоздями прибито include /etc/nginx/sites-enabled/default; и nginx естественно падает когда не находит этот конфиг
Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.
Пока нет других ответов. Будьте первым, кто поможет автору.
Ответить на вопрос


Проблема с путем /sanctum/csrf-cookie может возникать по нескольким причинам. Вот несколько возможных причин и способы их решения:
1. Неправильная настройка маршрутов: Убедитесь, что у вас правильно настроены маршруты для Sanctum в файле routes/api.php. Должно быть что-то вроде Route::middleware('auth:sanctum')->get('/sanctum/csrf-cookie', function (Request $request) { return response()->json(); });
2. Неправильная конфигурация CORS: Если у вас возникают проблемы с CORS, убедитесь, что вы правильно настроили CORS для вашего проекта. Убедитесь, что ваш сервер возвращает заголовки Access-Control-Allow-Origin и Access-Control-Allow-Credentials для запросов к /sanctum/csrf-cookie.
3. Проблемы с сеансами: Убедитесь, что у вас правильно настроены сеансы в вашем приложении Laravel. Sanctum требует наличия сеансов для хранения CSRF-токенов. Убедитесь, что у вас включен драйвер сеансов в файле config/session.php и что вы используете Cookie драйвер.
4. Проверьте наличие CSRF-токена: Убедитесь, что ваш фронтенд приложение отправляет правильный CSRF-токен при запросе к /sanctum/csrf-cookie. Для этого вы можете использовать функцию csrf_token() в Blade шаблонах или csrf_token() в JavaScript, если вы работаете с API.
Если после проверки всех вышеперечисленных пунктов проблема с путем /sanctum/csrf-cookie все еще не решена, попробуйте обновить зависимости вашего проекта или переустановить Sanctum. Если проблема сохраняется, обратитесь за помощью к сообществу разработчиков на форумах или в чате разработчиков Laravel.