Получение 401 несанкционированного доступа для Laravel sanctum
Я использую Laravel Sanctum с Vuejs SPA. Оба находятся в одном домене верхнего уровня
Laravel backend : app.demo.localhost
Vue SPA : app-spa.demo.localhost
Вход и выход из системы (конечные точки) работают правильно при вызове из VueJS SPA с использованием axios и успешно установлен XSRF-TOKEN, но когда я вызываю другие конечные точки api, он дает мне 401 неавторизованный.
В аксиомах это устанавливается
axios.defaults.withCredentials = true;
У меня есть следующие конфигурации
В Laravel .env
SESSION_DRIVER=cookie
SESSION_DOMAIN=.demo.localhost
SANCTUM_STATEFUL_DOMAINS=app-spa.demo.localhost
В Routes/Api.php
Route::middleware('auth:sanctum')->get('api/user', function (Request $request) {
return $request->user();
});
В cors.php
'paths' => ['api/*', 'sanctum/csrf-cookie', 'login', 'logout'],
'allowed_methods' => ['*'],
'allowed_origins' => ['*'],
'allowed_origins_patterns' => [],
'allowed_headers' => ['*'],
'exposed_headers' => [],
'max_age' => 0,
'supports_credentials' => true,
Может кто-нибудь мне помочь?
10 ответов
Если вы используете php artisan serve, добавьте номер порта в SANCTUM_STATEFUL_DOMAINS. Итак, если ваш номер порта 8000:
SESSION_DRIVER=cookie
SESSION_DOMAIN=.demo.localhost
SANCTUM_STATEFUL_DOMAINS=app-spa.demo.localhost:8000
Ваш SANCTUM_STATEFUL_DOMAINS должен соответствовать URL-адресу в вашем браузере. Номер порта не должен находиться в SESSION_DOMAIN.
Ниже приведены 8 шагов, которые я выполняю при настройке проверки святилища Laravel, если вы что-то пропустили.
Шаг 1
composer require laravel/sanctum
Шаг 2
php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider
Шаг 3
php artisan migrate
(вы можете игнорировать это, если используете спа)
Шаг 4 раскомментируйте эту строку из app / http / kernel.php
\Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
Шаг 5 В config / cors.php update
'supports_credentials' => true,
Шаг 6 В обновлении файла .env
SESSION_DRIVER=cookie
и добавить новую строку
SESSION_DOMAIN=localhost
(даже если вы используете какой-либо порт, например 8080, просто укажите localhost в session_domain)
Шаг 7 В config / sanctum.php добавьте свой клиентский домен вместе с портом (если он локальный) с сохранением состояния следующим образом, в моем случае для vue CLI это обычно
localhost:8080
и для этого
localhost:3000
, код выглядит следующим образом
'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf(
'%s%s',
'localhost,localhost:8000,localhost:8080,localhost:3000,127.0.0.1,127.0.0.1:8000,::1',
env('APP_URL') ? ','.parse_url(env('APP_URL'), PHP_URL_HOST) : ''
))),
В основном, если ваше состояние (шаг 7) не настроено должным образом, вы получите 401 неавторизованный или он попытается перенаправить вас на домашнюю страницу вместе с ошибкой политики cors
Step8 Не забудьте
await
до
sanctum/csrf-cookie
обещание решено
async login() {
await axios.get("http://localhost:8000/sanctum/csrf-cookie");
await axios.post("http://localhost:8000/login", {
email: "kunal@gmail.com",
password: "password",
});
let response = await axios.get("http://localhost:8000/api/user");
console.log(response.data);
},
Для тех, кто имеет дело с localhost:
SESSION_DRIVER=cookie
SESSION_DOMAIN=localhost
SANCTUM_STATEFUL_DOMAINS=localhost:8080(port number you use)
Для меня мне просто нужно было разместить хост с номером порта:
SANCTUM_STATEFUL_DOMAINS=127.0.0.1:5173
и он начал работать. Может быть, это кому-то поможет.
Я столкнулся с той же проблемой. Я настроил все параметры согласно официальной документации, но получить авторизацию не удалось.
Затем я использую routes/web.php вместо routes/api.php, поэтому я могу очень хорошо использовать промежуточное программное обеспечение sanctum.
Теперь проблема кажется очевидной: Axios withCredentials, возможно, нужно разместить правильно.
const http = axios.create({
baseURL: API_URL,
withCredentials: true
})
может не получится. Я добавляю{withCredentials: true}
подобно
http.get('/api/whoami', {withCredentials: true})
.then(res => {
console.log(res.data)
})
Тогда это работает.
Но очень странно то, что сейчас это нормально, независимо от того, очищаю ли я кеш браузера, файлы cookie или различные кеши Laravel, предыдущей ситуации нет.
Моя проблема заключалась в том, что я настроил домен в неправильном месте. Я думал, что это массив доменов, в
config/sanctum.php
, но не должен быть помещен в строку:
ХОРОШО:
'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf(
'%s%s',
'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1,myownlocaldomain.test,myownlocaldomain.test:8080', <-------- OK
env('APP_URL') ? ','.parse_url(env('APP_URL'), PHP_URL_HOST) : ''
))),
ПЛОХО:
'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf(
'%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) : '',
'myownlocaldomain.test', <----- BAD
'myownlocaldomain.test:8080', <---- BAD
))),
Я надеюсь, что сэкономлю дни работы кому-то другому...
Привет, я нашел решение.
Мой SPA - это Vue v3, работающий на порту 3000. Также мой бэкэнд работает на 80 порту. (ларавель 8.1)
Сделайте Stateful Domains в config/sanctum.php вот так
'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf(
'%s%s',
'localhost:3000',
env('APP_URL') ? ','.parse_url(env('APP_URL'), PHP_URL_HOST) : ''
))),
Добавление только одного и правильного домена у меня сработало волшебным образом. Я уже писал там весь возможный вариант портов, меня это взбесило и стоило пары дней и ночей.
Моя проблема была .... (не читать внимательно)
Если вашему SPA необходимо аутентифицироваться с помощью частных каналов / каналов присутствия, вы должны поместить вызов метода Broadcast ::routes в свой файл routes / api.php :
Laravel 10 с пакетом VueJs 3 и Sanctum. Я решил эту проблему, установивAPP_URL=[my domain name]
в.env
файл, значение которого соответствует имени домена в веб-браузере.
Попробуйте это. Надеюсь, поможет.
Ваше SPA, которое должно быть собственным приложением, не является собственным приложением, если оно находится на другом порту. Так что в вашей среде разработки оно действует как мобильное приложение.
Например
API Ларавел
localhost:8000
Приложение Vuejs
locahost:5781
Поэтому вам необходимо аутентифицировать его, отправляя заголовок авторизации при разработке на вашем локальном хосте. Примечание. Делайте это только в вашей локальной среде разработки. Поэтому поместите приведенный ниже код в if.
axios.interceptors.request.use(
config => {
// Do something before request is sent
if(process.env.dev) {
// accessToken was set after a successful login
const accessToken = localStorage.getItem('accessToken')
if (accessToken) config.headers.Authorization = `Bearer ${accessToken}`
}
return config
},
error => Promise.reject(error),
)