Аутентификация

Аутентификация — это процесс проверки личности пользователя. Представьте, что вы входите в здание по пропуску: система проверяет, кто вы и есть ли у вас доступ. В Imhotep аутентификация работает так же — система проверяет учетные данные пользователя и предоставляет доступ к защищенным ресурсам.

Imhotep предлагает гибкую систему аутентификации с поддержкой нескольких guards (стражей) и user providers (провайдеров пользователей). Это позволяет использовать разные способы аутентификации для разных частей вашего приложения.

Конфигурирование

Все настройки аутентификации находятся в файле config/auth.php. Этот файл содержит несколько ключевых разделов:

  • guards (стражи), определяют, как происходит аутентификация — через сессии, токены или другие методы.
  • providers (провайдеры), определяют, откуда берутся пользователи — из базы данных, массива или других источников.
  • default, указывает, какой страж используются по умолчанию.

Стражи аутентификации

Стражи определяют, как будет происходить аутентификация. Imhotep поставляется с несколькими готовыми стражами:

Session Guard

Использует сессии для хранения информации об аутентификации. Идеально подходит для веб-приложений с традиционными формами входа.

// config/auth.php
'guards' => [
    'web' => [
        'driver' => 'session',
        'provider' => 'users',
        'remember' => 1209600, // Время жизни "запомнить меня" в секундах (2 недели)
    ],
],
PHP

Token Guard

Использует токены для аутентификации. Подходит для API и мобильных приложений.

// config/auth.php
'guards' => [
    'api' => [
        'driver' => 'token',
        'provider' => 'users',
        'input_key' => 'api_token',   // Ключ, по которому искать токен
        'storage_key' => 'api_token', // Поле в базе данных для хранения токена
        'hash' => false,              // Хранить токен в хешированном виде
    ],
],
PHP

Провайдеры пользователей

Провайдеры определяют, как система получает данные о пользователях.

Database Provider

Получает пользователей из базы данных.

// config/auth.php
'providers' => [
    'users' => [
        'driver' => 'database',
        'table' => 'users',
        'user' => App\Models\User::class, // Опционально: класс модели пользователя
    ],
],
PHP

Array Provider

Использует массив пользователей, идеально для тестирования или некритичных систем.

// config/auth.php
'providers' => [
    'admins' => [
        'driver' => 'array',
        'users' => [
            'admin@example.com' => [
                'id' => 1,
                'email' => 'admin@example.com',
                'password' => 'password123',
                'name' => 'Admin',
            ],
        ],
    ],
],
PHP

Модель пользователя

Для использования аутентификации ваша модель пользователя должна реализовывать интерфейс Imhotep\Contracts\Auth\Authenticatable. Проще всего использовать трейт Imhotep\Auth\Traits\Authenticatable:

namespace App\Models;

use Imhotep\Auth\Traits\Authenticatable;
use Imhotep\Contracts\Auth\Authenticatable as AuthenticatableContract;

class User implements AuthenticatableContract
{
    use Authenticatable;
    
    // Получить имя первичного ключа
    // public function getAuthIdName(): string;
    
    // Получить значение первичного ключа
    // public function getAuthId(): mixed;
    
    // Получить хешированный пароль
    // public function getAuthPassword(): string;
    
    // Получить токен "запомнить меня"
    // public function getRememberToken(): ?string;
    
    // Установить токен "запомнить меня"
    // public function setRememberToken(string $value): void;
    
    // Получить имя поля для токена "запомнить меня"
    // public function getRememberTokenName(): string;
}
PHP

Аутентификация в действии

Ручной вход

Для входа пользователя используется фасад Auth:

namespace App\Controllers;

use App\Models\User;
use Imhotep\Facades\Hash;
use Imhotep\Facades\Auth;
use Imhotep\Http\Request;

class AuthController
{
    public function login(Request $request)
    {
        $email = $request->post('email');
        $password = $request->post('password');
        $remember = (bool) $request->post('remember', false);
        
        $user = User::email($email)->first();
        
        if (!$user || !Hash::check($password, $user->password)) {
            return response()->json(['error' => 'Неверные учетные данные'], 401);
        }
        
        // Аутентифицируем пользователя
        Auth::login($user, $remember);
        
        return response()->json(['message' => 'Добро пожаловать!']);
    }
}
PHP

Вход с проверкой учетных данных

Метод attempt проверяет учетные данные и автоматически выполняет вход:

namespace App\Controllers;

use Imhotep\Facades\Auth;
use Imhotep\Http\Request;

class AuthController
{
    public function login(Request $request)
    {
        $credentials = $request->only(['email', 'password']);
        $remember = (bool) $request->post('remember', false);
        
        if (Auth::attempt($credentials, $remember)) {
            // Вход выполнен успешно
            return response()->json(['message' => 'Добро пожаловать!']);
        }
        
        return response()->json(['error' => 'Неверные учетные данные'], 401);
    }
}
PHP

Вход по ID

namespace App\Controllers;

use App\Models\User;
use Imhotep\Facades\Auth;

class AuthController
{
    public function loginAsUser(int $id)
    {
        $user = User::find($id);
        
        if ($user && Auth::loginUsingId($id)) {
            return response()->json(['message' => 'Вы вошли как ' . $user->name]);
        }
        
        return response()->json(['error' => 'Пользователь не найден'], 404);
    }
}
PHP

Выход из системы

namespace App\Controllers;

use Imhotep\Facades\Auth;

class AuthController
{
    public function logout()
    {
        Auth::logout();
        
        return response()->json(['message' => 'Вы вышли из системы']);
    }
}
PHP

Проверка статуса пользователя

// Проверить, аутентифицирован ли пользователь
if (Auth::check()) {
    // Пользователь вошел
}

// Проверить, не аутентифицирован ли пользователь
if (Auth::guest()) {
    // Пользователь не вошел
}

// Получить текущего пользователя
$user = Auth::user();

// Получить ID текущего пользователя
$userId = Auth::id();

// Проверить, есть ли установленный пользователь
if (Auth::hasUser()) {
    // Пользователь установлен
}
PHP

Защита маршрутов

Использование middleware

Защитите маршруты с помощью middleware auth:

// В файле routes/web.php или routes/api.php

Route::get('/profile', 'ProfileController@index')
    ->middleware('auth');

Route::get('/dashboard', function () {
    return view('dashboard');
})->middleware('auth');

// С указанием конкретного стража
Route::get('/admin', 'AdminController@index')
    ->middleware('auth:admin');
PHP

Использование конкретного стража

// Явное указание стража
$user = Auth::guard('api')->user();

// Проверка через конкретный страж
if (Auth::guard('web')->check()) {
    // Пользователь аутентифицирован через web страж
}
PHP

Функция "Запомнить меня"

Для реализации "запомнить меня" используйте параметр remember:

public function login(Request $request)
{
    $credentials = $request->only(['email', 'password']);
    $remember = $request->has('remember');
    
    if (Auth::attempt($credentials, $remember)) {
        // Вход выполнен с сохранением сессии
        return redirect()->intended('dashboard');
    }
}
PHP

В модели пользователя должен быть определено поле для хранения токена:

use Imhotep\Auth\Traits\Authenticatable;
use Imhotep\Contracts\Auth\Authenticatable as AuthenticatableContract;

class User implements AuthenticatableContract
{
    use Authenticatable;
    
    protected string $rememberToken = 'remember_token'; // Имя поля в БД
    
    // Если у вас другое имя поля, установите его
    public function setRememberTokenName(string $name): void
    {
        $this->rememberToken = $name;
    }
}
PHP

HTTP Basic Authentication

Для быстрой защиты API можно использовать HTTP Basic Authentication:

// В контроллере
use Imhotep\Auth\Middleware\AuthenticateBasic;
use Imhotep\Facades\Auth;

public function getData(Request $request)
{
    // Добавьте middleware
    return response()->json(['data' => 'Защищенные данные']);
}

// В routes.php
Route::get('/api/data', 'DataController@getData')
    ->middleware('auth.basic');

// С указанием поля для email
Route::get('/api/data', 'DataController@getData')
    ->middleware('auth.basic:web,email');
PHP

События аутентификации

Imhotep генерирует события при различных действиях с аутентификацией. Вы можете подписаться на них для дополнительной логики:

namespace App\Listeners;

use Imhotep\Auth\Events\Login;
use Imhotep\Auth\Events\Logout;
use Imhotep\Auth\Events\Authenticated;
use Imhotep\Auth\Events\Attempting;
use Imhotep\Auth\Events\Failed;
use Imhotep\Auth\Events\Validated;
use Imhotep\Auth\Events\Registered;

class AuthEventListener
{
    public function onLogin(Login $event)
    {
        Log::info('Пользователь вошел', [
            'user_id' => $event->user?->getAuthId(),
            'guard' => $event->guard,
            'remember' => $event->remember
        ]);
    }
    
    public function onLogout(Logout $event)
    {
        Log::info('Пользователь вышел', [
            'user_id' => $event->user->getAuthId(),
            'guard' => $event->guard
        ]);
    }
    
    public function onAuthenticated(Authenticated $event)
    {
        // Пользователь аутентифицирован
    }
    
    public function onAttempting(Attempting $event)
    {
        // Попытка аутентификации
        Log::info('Попытка входа', [
            'credentials' => array_keys($event->credentials),
            'remember' => $event->remember
        ]);
    }
    
    public function onFailed(Failed $event)
    {
        // Неудачная попытка аутентификации
        Log::warning('Неудачный вход', [
            'user_id' => $event->user?->getAuthId(),
            'credentials' => array_keys($event->credentials)
        ]);
    }
    
    public function onValidated(Validated $event)
    {
        // Учетные данные проверены успешно
    }
    
    public function onRegistered(Registered $event)
    {
        // Пользователь зарегистрирован
    }
}
PHP

Создание собственных провайдеров пользователей

Аналогично, вы можете создать свой провайдер пользователей:

// В сервис-провайдере
use Imhotep\Contracts\Auth\Factory;

class AuthServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        $this->app->make(Factory::class)->extendProvider('custom', function ($app, $config) {
            return new CustomUserProvider($config);
        });
    }
}
PHP

Рекомендации

  • Всегда хешируйте пароли — используйте Hash::make() перед сохранением.
  • Используйте CSRF-защиту для веб-форм входа.
  • Ограничьте попытки входа для защиты от брутфорса.
  • Используйте HTTPS в production для защиты учетных данных.
  • Регулярно обновляйте ключи шифрования сессий.