Сессионная аутентификация для веб-приложения
Сессионная аутентификация — классический подход: при логине создаётся запись в хранилище сессий, клиенту отдаётся cookie с session_id. На каждый запрос сервер ищет сессию по ID и восстанавливает контекст пользователя. Stateful — состояние хранится на сервере. Надёжна, проста в реализации, легко отзываема.
Когда сессии лучше JWT
Сессии предпочтительнее для:
- Традиционных веб-приложений с SSR (Blade, Twig, ERB)
- Когда нужен мгновенный logout (не ждать истечения токена)
- Хранения больших данных состояния без передачи в cookie
- Приложений с ограниченным количеством пользователей
JWT предпочтительнее для:
- API, потребляемых мобильными приложениями
- Микросервисной архитектуры
- Горизонтального масштабирования без центрального хранилища сессий
Laravel Session
// config/session.php — критические настройки
return [
'driver' => env('SESSION_DRIVER', 'redis'), // redis/database/file
'lifetime' => 120, // минуты
'expire_on_close' => false, // сессия переживает закрытие браузера
'encrypt' => true, // шифрование данных сессии
'secure' => true, // cookie только через HTTPS
'http_only' => true, // недоступен для JS
'same_site' => 'lax', // CSRF-защита
'domain' => '.example.com', // для поддоменов
];
Redis как хранилище сессий — масштабируемо, быстро. Без Redis при нескольких серверах у пользователей будут «вылеты» при балансировке:
# .env
SESSION_DRIVER=redis
REDIS_SESSION_DB=1 # отдельная БД Redis для сессий
Auth::login и remember me
public function login(LoginRequest $request)
{
$credentials = $request->only('email', 'password');
$remember = $request->boolean('remember');
if (!Auth::attempt($credentials, $remember)) {
throw ValidationException::withMessages([
'email' => [trans('auth.failed')],
]);
}
$request->session()->regenerate(); // предотвращает Session Fixation
return redirect()->intended('/dashboard');
}
public function logout(Request $request)
{
Auth::logout();
$request->session()->invalidate(); // удаляет сессию
$request->session()->regenerateToken(); // новый CSRF token
return redirect('/');
}
remember me работает через долгоживущий cookie с хэшем токена — Laravel автоматически восстанавливает сессию при следующем визите.
Session Fixation и CSRF
Session Fixation: атакующий подсовывает жертве session_id до логина, после логина получает доступ к её сессии. Защита — session()->regenerate() сразу после успешного логина. Laravel делает это автоматически.
CSRF: для всех форм обязателен @csrf (Blade) или X-CSRF-Token заголовок для AJAX. Laravel проверяет токен через VerifyCsrfToken middleware.
// Axios — автоматически добавляет CSRF токен
import axios from 'axios';
axios.defaults.withCredentials = true;
axios.defaults.headers.common['X-CSRF-TOKEN'] = document.querySelector('meta[name="csrf-token"]')?.getAttribute('content');
// Fetch API — cookies отправляются с credentials: 'include'
const res = await fetch('/api/user', {
credentials: 'include',
headers: { 'X-CSRF-TOKEN': getCsrfToken() },
});
Управление несколькими устройствами
// Получение всех активных сессий пользователя
$sessions = DB::table('sessions')
->where('user_id', auth()->id())
->orderByDesc('last_activity')
->get()
->map(fn($s) => [
'id' => $s->id,
'ip' => $s->ip_address,
'user_agent' => $s->user_agent,
'last_active' => Carbon::createFromTimestamp($s->last_activity)->diffForHumans(),
'is_current' => $s->id === request()->session()->getId(),
]);
// Завершить все сессии кроме текущей
public function logoutOtherDevices(Request $request)
{
Auth::logoutOtherDevices($request->input('password'));
return redirect('/settings/sessions')
->with('status', 'Другие сессии завершены');
}
Хранение сессий в базе данных
php artisan session:table
php artisan migrate
// config/session.php
'driver' => 'database',
'table' => 'sessions',
Таблица sessions: id, user_id (nullable), ip_address, user_agent, payload (зашифровано), last_activity.
Индекс на user_id обязателен для запроса «все сессии пользователя». Очистка устаревших сессий:
php artisan session:gc # или через Scheduler
SPA + Laravel Sanctum (cookie-based)
Для SPA, где фронтенд и API на одном домене — Sanctum в режиме cookie предпочтительнее JWT:
// Инициализация CSRF
// Клиент: GET /sanctum/csrf-cookie — устанавливает XSRF-TOKEN cookie
// После этого все POST/PUT/DELETE запросы автоматически включают токен
Route::middleware('auth:sanctum')->get('/api/user', fn(Request $r) => $r->user());
Sanctum в cookie-режиме = сессии с дополнительной защитой. API токены — отдельная фича Sanctum для мобильных клиентов.
Сроки
Сессионная аутентификация с Redis, remember me, CSRF-защитой, логаутом со всех устройств: 1–2 дня. С UI управления сессиями, аудит-логом входов (IP, устройство, геолокация), детектированием подозрительных входов: 3–5 дней.







