Вопрос или проблема
У меня есть бэкенд на Laravel и фронтенд на React Native. Я хочу защитить API маршруты, к которым обращается мое приложение React Native с помощью Axios, для этого я установил Laravel Sanctum.
Мой текущий рабочий процесс: я логинюсь или регистрирую пользователя с помощью электронной почты и пароля, получаю токен Sanctum, который храню с помощью AsyncStorage в своем приложении, затем отправляю этот токен в заголовках всех своих вызовов Axios, используя перехватчики.
ПРОБЛЕМА:
Маршруты, защищенные middleware auth:sanctum, получают 302 Found, а затем перенаправляются на главную страницу / 200 OK.
Как я создаю токен на бэкенде:
$token = $user->createToken($request['device_name'])->plainTextToken;
Как я добавляю свой Bearer токен в заголовки (я проверяю, что они прикреплены через консольный лог):
if (token)
{
console.log('SANCTUM: Добавление bearer токена в axios: ' + token);
axios.defaults.headers.common['Authorization'] = 'Bearer ' + token;
}
Как я защищаю свои маршруты:
Route::get('/auth/sanctum/user', 'App\Http\Controllers\Api\AuthController@sanctumUser')->middleware('auth:sanctum');
В моем middleware RedirectIfAuthenticated я пытался изменить его после чтения некоторых других постов, но любые изменения, которые я сделал, не дали никакого результата…
<?php
namespace App\Http\Middleware;
use App\Providers\RouteServiceProvider;
use Closure;
use Illuminate\Support\Facades\Auth;
class RedirectIfAuthenticated
{
/**
* Обработка входящего запроса.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @param string|null ...$guards
* @return mixed
*/
//Добавил часть && !$request->wantsJson()
public function handle($request, Closure $next, ...$guards)
{
$guards = empty($guards) ? [null] : $guards;
foreach ($guards as $guard)
{
//Добавил !$request->wantsJson()
if (Auth::guard($guard)->check() && !$request->wantsJson() )
{
//Пытался изменить это тоже
return redirect(RouteServiceProvider::HOME);
}
}
return $next($request);
}
}
В моем Kernel http:
protected $middlewareGroups = [
'web' => [
//\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
//\Illuminate\Session\Middleware\StartSession::class,
//\Illuminate\Session\Middleware\AuthenticateSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
'api' => [
//EnsureFrontendRequestsAreStateful::class,
\Illuminate\Routing\Middleware\ThrottleRequests::class.':api',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
];
Файл sanctum.php
<?php
return [
/*
|--------------------------------------------------------------------------
| Состояние доменов
|--------------------------------------------------------------------------
|
| Запросы из следующих доменов / хостов будут получать куки
| аутентификации API с состоянием. Как правило, это должны быть ваши локальные
| и рабочие домены, которые получают доступ к вашему API через фронтенд SPA.
|
*/
'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', 'localhost,127.0.0.1,127.0.0.1:8000,::1')),
/*
|--------------------------------------------------------------------------
| Время истечения
|--------------------------------------------------------------------------
|
| Это значение контролирует количество минут, в течение которых выданный токен будет
| считаться просроченным. Если это значение равно null, токены доступа
| не истекают. Это не изменит срок действия сеансов для первых сторон.
|
*/
'expiration' => null,
/*
|--------------------------------------------------------------------------
| Middleware Sanctum
|--------------------------------------------------------------------------
|
| При аутентификации вашего SPA от первой стороны с помощью Sanctum вам может понадобиться
| настроить некоторые из middleware, которые использует Sanctum при обработке запроса.
| Вы можете изменить перечисленный ниже middleware по мере необходимости.
|
*/
'middleware' => [
'verify_csrf_token' => App\Http\Middleware\VerifyCsrfToken::class,
'encrypt_cookies' => App\Http\Middleware\EncryptCookies::class,
],
];
Файл auth.php:
<?php
return [
/*
|--------------------------------------------------------------------------
| Настройки аутентификации по умолчанию
|--------------------------------------------------------------------------
|
| Эта опция контролирует "охрану" аутентификации по умолчанию и параметры сброса пароля
| для вашего приложения. Вы можете изменить эти параметры
| по мере необходимости, но это хорошее начало для большинства приложений.
|
*/
'defaults' => [
'guard' => 'web',
'passwords' => 'users',
],
/*
|--------------------------------------------------------------------------
| Охраны аутентификации
|--------------------------------------------------------------------------
|
| Далее вы можете определить каждую охрану аутентификации для вашего приложения.
| Конечно, для вас здесь определена отличная базовая конфигурация,
| которая использует хранилище сеансов и провайдер пользователей Eloquent.
|
| У всех драйверов аутентификации есть провайдер пользователей. Это определяет, как
| пользователи фактически извлекаются из вашей базы данных или других методов хранения,
| используемых этим приложением для сохранения данных ваших пользователей.
|
| Поддерживаемые: "session", "token"
|
*/
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'token',
'provider' => 'users',
'hash' => false
],
],
/*
|--------------------------------------------------------------------------
| Провайдеры пользователей
|--------------------------------------------------------------------------
|
| У всех драйверов аутентификации есть провайдер пользователей. Это определяет, как
| пользователи фактически извлекаются из вашей базы данных или других методов хранения,
| используемых этим приложением для сохранения данных ваших пользователей.
|
| Если у вас есть несколько таблиц или моделей пользователей, вы можете настроить несколько
| источников, которые представляют каждую модель / таблицу. Эти источники затем могут
| быть назначены к любым дополнительным охранам аутентификации, которые вы определили.
|
| Поддерживаемые: "database", "eloquent"
|
*/
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\Models\User::class,
],
// 'users' => [
// 'driver' => 'database',
// 'table' => 'users',
// ],
],
/*
|--------------------------------------------------------------------------
| Сброс паролей
|--------------------------------------------------------------------------
|
| Вы можете указать несколько конфигураций сброса паролей, если у вас есть более одной
| таблицы или модели пользователей в приложении, и вы хотите, чтобы у вас были
| отдельные настройки сброса паролей в зависимости от конкретных типов пользователей.
|
| Время истечения — это количество минут, в течение которых токен сброса должен считаться
| действительным. Эта функция безопасности поддерживает токены короткоживущими, чтобы
| у них было меньше времени для угадывания. Вы можете изменить это по мере необходимости.
|
*/
'passwords' => [
'users' => [
'provider' => 'users',
'table' => 'password_resets',
'expire' => 60,
'throttle' => 60,
],
],
/*
|--------------------------------------------------------------------------
| Время ожидания подтверждения пароля
|--------------------------------------------------------------------------
|
| Здесь вы можете определить количество секунд, прежде чем подтверждение пароля
| истечет, и пользователю будет предложено ввести свой пароль повторно через
| экран подтверждения. По умолчанию тайм-аут составляет три часа.
|
*/
'password_timeout' => 10800,
];
Ответ или решение
Чтобы решить проблему с получением 302 редиректов на главную страницу в вашем приложении Laravel и React Native при использовании Sanctum для защиты API маршрутов, давайте разберем возможные причины и решения:
1. Проблема с конфигурацией Sanctum
Убедитесь, что ваш файл конфигурации sanctum.php
правильно настроен для работы с React Native. В частности, убедитесь, что SANCTUM_STATEFUL_DOMAINS
в вашем .env
файле настроен правильно. Этот параметр должен включать адрес вашего React Native приложения, особенно если вы используете эмулятор (например, localhost
или IP-адрес вашего компьютера). Пример обновления:
SANCTUM_STATEFUL_DOMAINS=localhost,127.0.0.1,192.168.0.100
Замените 192.168.0.100
на IP-адрес вашего компьютера, если ваше приложение подключается через локальную сеть.
2. Проблемы с CORS
Убедитесь, что у вас настроены правильные заголовки CORS. Проверьте файл cors.php
, который находится в config
. Например, добавьте ваш фронтенд домен:
'paths' => ['api/*'],
'allowed_methods' => ['*'],
'allowed_origins' => ['http://localhost:3000', 'http://192.168.0.100:3000'],
'allowed_headers' => ['*'],
'exposed_headers' => [],
'max_age' => 0,
'supports_credentials' => true,
3. Проблемы с маршрутизацией
Проверьте, правильно ли вы защищаете маршруты. Например, убедитесь, что маршрут, который вы используете (/auth/sanctum/user
), а также контроллер AuthController
, работают как ожидалось и возвращают корректную информацию о пользователе, когда аутентификация прошла успешно.
4. Проверьте настройки Middleware
Убедитесь, что EnsureFrontendRequestsAreStateful
добавлен в вашу группу middleware API. Это позволит Sanctum обрабатывать запросы от вашего React Native приложения корректно.
'api' => [
\Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
\Illuminate\Routing\Middleware\ThrottleRequests::class.':api',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
5. Использование token
Убедитесь, что вы правильно добавляете токен в заголовки вашего Axios. Вот пример кода для установки токена:
if (token) {
console.log('SANCTUM: Adding bearer token to axios: ' + token);
axios.defaults.headers.common['Authorization'] = `Bearer ${token}`;
}
Также проверьте, что ваш токен действительно сохраняется и используется на всех запросах.
6. Проверка ошибок на сервере
Используйте инструменты для отладки (например, dd()
в Laravel) в контроллере, чтобы проверить, поступают ли запросы с правильными заголовками и токенами. Это поможет вам определить, правильно ли обрабатываются запросы на стороне сервера.
7. Проверка состояния сессий
Если вы продолжаете сталкиваться с проблемами, попробуйте отключить куки и сессии в вашем приложении React Native, так как это может вызвать дополнительные сложности при работе с Sanctum.
Заключение
Перепроверив все эти настройки один за другим, вы должны быть в состоянии выявить причину 302 редиректов на вашу домашнюю страницу. Убедитесь, что вы перезапустили сервер после изменения любых конфигураций, и тестируйте с обновленной версией вашего приложения.