Первый шаг — оценка текущей реализации. Предположим, у вас есть Laravel-бэкенд, который выдает JWT через кастомный guard или пакет вроде `tymon/jwt-auth`. Фронтенд (Vue.js/React) хранит токен в localStorage и отправляет его в заголовке `Authorization: Bearer `. Проблемы: чтобы разлогинить пользователя, нужно ждать истечения срока жизни токена (TTL); компрометация токена дает доступ до его экспирации; сложная логика обновления refresh-токенов.
Шаг 2: Выбор целевого решения. Laravel предлагает два основных инструмента:
- **Sanctum**: Идеально для SPA, работающих на том же домене (или с правильно настроенным CORS), и для мобильных приложений. Он предоставляет легковесную аутентификацию на основе сессий для браузерных SPA и токенов API для мобильных клиентов. Токены Sanctum можно легко отозвать.
- **Passport**: Полноценная реализация OAuth2 сервера. Подходит, если у вас есть несколько клиентов (веб, мобильное, сторонние приложения), требующих стандартизированный протокол. Более тяжеловесный, но и более функциональный.
Шаг 3: Установка и настройка Sanctum. Установите пакет через Composer.
composer require laravel/sanctum
Опубликуйте конфигурации и миграции.
php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
Выполните миграцию для создания таблицы `personal_access_tokens`.
php artisan migrate
Добавьте middleware `\Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class` в группу `api` в `app/Http/Kernel.php`. Это ключевой момент: для запросов из SPA Sanctum будет использовать сессии (куки), а для мобильных — токены.
Шаг 4: Адаптация модели User. Убедитесь, что ваша модель `User` использует трейт `Laravel\Sanctum\HasApiTokens`.
use Laravel\Sanctum\HasApiTokens;
class User extends Authenticatable
{
use HasApiTokens, HasFactory, Notifiable;
}
Шаг 5: Модификация контроллеров аутентификации. Перепишите ваш `AuthController`. Эндпоинт входа вместо генерации JWT будет выполнять стандартную попытку входа через `Auth::attempt` и создавать сессию (для SPA) или токен (для мобильных).
public function login(Request $request)
{
$credentials = $request->only('email', 'password');
if (Auth::attempt($credentials)) {
$user = Auth::user();
// Для мобильного клиента или стороннего API создаем токен
if ($request->wantsJson() || $request->is('api/*')) {
$token = $user->createToken('auth_token')->plainTextToken;
return response()->json([
'user' => $user,
'access_token' => $token,
'token_type' => 'Bearer',
]);
}
// Для SPA на том же домене аутентификация через сессию произойдет автоматически
return response()->json(['user' => $user]);
}
return response()->json(['error' => 'Unauthorized'], 401);
}
Шаг 6: Защита маршрутов API. Вместо кастомного JWT middleware теперь используйте встроенный `auth:sanctum`. Он будет проверять либо аутентифицированную сессию (для SPA), либо валидный токен из заголовка `Authorization: Bearer ...`.
Route::middleware('auth:sanctum')->group(function () {
Route::get('/user', function (Request $request) {
return $request->user();
});
// Ваши защищенные маршруты, например, для видео
Route::post('/video/upload', [VideoController::class, 'upload']);
});
Шаг 7: Адаптация фронтенда (SPA на том же домене). Это самый простой сценарий. Убедитесь, что ваш фронтенд отправляет запросы с `credentials: 'include'` (в axios: `axios.defaults.withCredentials = true;`). Удалите всю логику ручного добавления JWT в заголовки. Sanctum автоматически будет использовать куки сессии Laravel. Запросы к API будут считаться аутентифицированными, если пользователь вошел в систему.
Шаг 8: Адаптация мобильного приложения или отдельного фронтенда. Для нативных приложений или SPA на другом домене используйте токен, полученный при логине. Сохраните `access_token` и отправляйте его в заголовке, как и раньше. Но теперь токен можно отозвать! Эндпоинт выхода должен удалять токен.
public function logout(Request $request)
{
// Отзыв текущего токена (для мобильных/токенов)
$request->user()->currentAccessToken()->delete();
// Или отзыв всех токенов: $request->user()->tokens()->delete();
// Для SPA также можно вызвать Auth::logout() для очистки сессии
Auth::guard('web')->logout();
return response()->json(['message' => 'Logged out']);
}
Шаг 9: Особенности работы с видеоконтентом. Если ваше приложение загружает или стримит видео, важно обеспечить защиту этих ресурсов. С JWT вы, возможно, передавали токен в параметре запроса или заголовке для доступа к видеофайлу. С Sanctum подход может быть аналогичным для токенов. Однако для SPA, обслуживающих видео через теги ``, браузер не отправляет куки сессии по умолчанию при cross-origin запросах. Решение: настроить CORS правильно (указав `credentials: true` на сервере) или использовать подписанные временные URL. Laravel может генерировать подписанные ссылки на защищенные видеофайлы, хранящиеся в S3 или локально, с ограниченным временем жизни.
use Illuminate\Support\Facades\Storage;
Route::middleware('auth:sanctum')->get('/video/{video}', function (Video $video) {
// Генерация подписанного URL на 10 минут для S3
$url = Storage::disk('s3')->temporaryUrl(
$video->path, now()->addMinutes(10)
);
return redirect($url);
});
Шаг 10: Инвалидация и управление токенами. Одно из главных преимуществ — панель управления токенами. Вы можете создать простой интерфейс, где пользователь видит список своих активных токенов (устройств) и может их отозвать. Данные хранятся в таблице `personal_access_tokens`.
В заключение, миграция с JWT на Sanctum делает ваше приложение более безопасным и управляемым. Вы получаете возможность мгновенного отзыва доступа, более простую интеграцию с SPA на одном домене и надежную основу для роста. Процесс требует изменений на бэкенде и адаптации фронтенда, но результат — профессиональная система аутентификации, соответствующая современным стандартам Laravel.
Комментарии (10)