Урок 8: Аутентификация в Symfony. Регистрация, роли, защита маршрутов

На 8-м уроке мы разберем важную тему в веб-разработке, это аутентификацию пользователей. Если вы создаете приложение, которое требует регистрации, входа в аккаунт или разделения прав доступа, Symfony предоставляет мощный инструмент Security Bundle. В этом уроке мы научимся настраивать аутентификацию, работать с ролями и защищать маршруты. Всё это будет с примерами кода и практическими задачами.

Установка Security Bundle

Symfony Security Bundle это компонент, который управляет аутентификацией, авторизацией и другими аспектами безопасности. Установим его через Composer:

bash
composer require symfony/security-bundle

После установки Symfony автоматически создаст файл конфигурации config/packages/security.yaml. Откройте его и проверьте настройки.
По умолчанию конфиг выглядит так:

yaml
security:
    enable_authenticator_manager: true
    providers:
        users_in_memory: { memory: null }
    firewalls:
        dev:
            pattern: ^/(_(profiler|wdt)|css|images|js)/
            security: false
        main:
            lazy: true
            provider: users_in_memory

Пока что здесь нет настроек для работы с базой данных. Мы исправим это позже, когда будем создавать сущность пользователя.

Регистрация и вход пользователя

Создание сущности User

Для работы с аутентификацией нам нужна сущность пользователя. Создадим ее:

bash
php bin/console make:user

Ответьте на вопросы:

  • Название класса: User
  • Хранить пользователей в базе данных: yes
  • Использовать username: no (выберем email)
  • Использовать пароль: yes

После выполнения команды Symfony сгенерирует класс User в директории src/Entity/. Проверьте, чтобы он реализовывал интерфейс UserInterface:

php
// src/Entity/User.php
namespace App\Entity;

use App\Repository\UserRepository;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\UserInterface;

#[ORM\Entity(repositoryClass: UserRepository::class)]
class User implements UserInterface
{
    #[ORM\Id]
    #[ORM\GeneratedValue]
    #[ORM\Column]
    private ?int $id = null;

    #[ORM\Column(length: 180, unique: true)]
    private ?string $email = null;

    #[ORM\Column]
    private array $roles = [];

    #[ORM\Column]
    private ?string $password = null;

    // Геттеры и сеттеры...
}

Настройка провайдера аутентификации

Обновим security.yaml, чтобы Symfony понимал, как искать пользователей:

yaml
security:
    providers:
        app_user_provider:
            entity:
                class: App\Entity\User
                property: email
    firewalls:
        main:
            provider: app_user_provider
            form_login:
                login_path: app_login
                check_path: app_login
                default_target_path: app_home
            logout:
                path: app_logout

Регистрация пользователя

Создадим форму регистрации. Для этого выполните:

bash
php bin/console make:registration-form

Symfony автоматически создаст контроллер, форму и шаблон. Проверьте маршруты:

php
// src/Controller/RegistrationController.php
#[Route('/register', name: 'app_register')]
public function register(Request $request, UserPasswordHasherInterface $passwordHasher): Response
{
    $user = new User();
    $form = $this->createForm(RegistrationFormType::class, $user);
    $form->handleRequest($request);

    if ($form->isSubmitted() && $form->isValid()) {
        // Хешируем пароль
        $user->setPassword(
            $passwordHasher->hashPassword(
                $user,
                $form->get('plainPassword')->getData()
            )
        );

        $entityManager = $this->getDoctrine()->getManager();
        $entityManager->persist($user);
        $entityManager->flush();

        return $this->redirectToRoute('app_home');
    }

    return $this->render('registration/register.html.twig', [
        'registrationForm' => $form->createView(),
    ]);
}

Вход пользователя

Создадим контроллер для входа:

php
// src/Controller/LoginController.php
#[Route('/login', name: 'app_login')]
public function login(AuthenticationUtils $authenticationUtils): Response
{
    $error = $authenticationUtils->getLastAuthenticationError();
    $lastUsername = $authenticationUtils->getLastUsername();

    return $this->render('login/index.html.twig', [
        'last_username' => $lastUsername,
        'error' => $error,
    ]);
}

Шаблон login/index.html.twig:

twig
{% extends 'base.html.twig' %}

{% block body %}
    {% if error %}
        <div class="alert alert-danger">{{ error.messageKey|trans(error.messageData, 'security') }}</div>
    {% endif %}

    <form method="post">
        <input type="email" name="_username" value="{{ last_username }}" placeholder="Email">
        <input type="password" name="_password" placeholder="Пароль">
        <button type="submit">Войти</button>
    </form>
{% endblock %}

Роли (ROLE_USER, ROLE_ADMIN)

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

Назначение ролей

Добавим поле roles в форму регистрации (если его нет) или назначим роли через консоль:

php
// src/Entity/User.php
public function getRoles(): array
{
    $roles = $this->roles;
    $roles[] = 'ROLE_USER'; // Гарантируем, что у всех есть ROLE_USER
    return array_unique($roles);
}

Чтобы назначить роль администратора, можно использовать консоль:

bash
php bin/console app:make-admin user@example.com

Реализуем команду:

php
// src/Command/MakeAdminCommand.php
#[AsCommand(name: 'app:make-admin')]
class MakeAdminCommand extends Command
{
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $user = $this->entityManager->getRepository(User::class)
            ->findOneBy(['email' => $email]);

        $user->setRoles(['ROLE_ADMIN']);
        $this->entityManager->flush();

        $output->writeln('Пользователь стал администратором!');
        return Command::SUCCESS;
    }
}

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

Через атрибуты контроллера

Используйте #[IsGranted], чтобы ограничить доступ:

php
use Symfony\Component\Security\Http\Attribute\IsGranted;

#[IsGranted('ROLE_ADMIN')]
#[Route('/admin', name: 'app_admin')]
public function adminDashboard(): Response
{
    // Только для администраторов
}

Через security.yaml

Добавьте правила в access_control:

yaml
security:
    access_control:
        - { path: ^/admin, roles: ROLE_ADMIN }
        - { path: ^/profile, roles: ROLE_USER }

Практические задачи

  1. Регистрация и вход. Создайте форму регистрации и входа. Проверьте, что после регистрации пользователь может войти в систему.
  2. Роли пользователей. Назначьте пользователю с email admin@example.com роль ROLE_ADMIN через консольную команду.
  3. Защита маршрута /admin. Создайте страницу /admin, доступную только администраторам. Используйте атрибут #[IsGranted('ROLE_ADMIN')].
  4. Кастомный Access Denied Handler. Реализуйте страницу с сообщением «Доступ запрещен», если пользователь пытается попасть в админку без прав.

Сегодня мы разобрали аутентификацию в Symfony, от установки Security Bundle до защиты маршрутов. Попрактикуйтесь с задачами, чтобы закрепить материал.

Хотите изучить Symfony от А до Я? Переходите на полный курс по Symfony для начинающих.

Поделиться статьей:
Поддержать автора блога

Поддержка автора осуществляется с помощью специальной формы ниже, предоставленной сервисом «ЮMoney». Все платёжные операции выполняются на защищённой странице сервиса, что обеспечивает их корректность и полную безопасность.

Персональные рекомендации
Оставить комментарий