Как создавать и подключать пользовательские программы проверки пользователя
Дата обновления перевода 2024-07-27
Как создавать и подключать пользовательские программы проверки пользователя
Во время аутентификации пользователя могут потребоваться дополнительные проверки для верификации того, разрешено ли пользователю выполнять вход. Определив пользовательскую программу проверки пользователя, вы можете определить, какую программу проверки использовать для каждого брандмауэера.
Создание пользовательской программы проверки пользователя
Программы проверки пользователя - это классы, которые должны реализовывать
UserCheckerInterface. Этот
интерфейс определяет два метода под названием checkPreAuth()
и checkPostAuth()
для выполнения проверок до и после аутентификации пользователя. Если не соблюдено
одно или более условий, должно быть вызвано исключение, которое расширяет
AccountStatusException.
Рассмотрите использование CustomUserMessageAccountStatusException,
который расширяет AccountStatusException
и позволяет настраивать сообщение об
ошибке, отображенное пользователю:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
namespace App\Security;
use App\Entity\User as AppUser;
use Symfony\Component\Security\Core\Exception\AccountExpiredException;
use Symfony\Component\Security\Core\Exception\CustomUserMessageAccountStatusException;
use Symfony\Component\Security\Core\User\UserCheckerInterface;
use Symfony\Component\Security\Core\User\UserInterface;
class UserChecker implements UserCheckerInterface
{
public function checkPreAuth(UserInterface $user): void
{
if (!$user instanceof AppUser) {
return;
}
if ($user->isDeleted()) {
// сообщение, переданное этому исключению, должно быть отображено пользователю
throw new CustomUserMessageAccountStatusException('Your user account no longer exists.');
}
}
public function checkPostAuth(UserInterface $user): void
{
if (!$user instanceof AppUser) {
return;
}
// у аккаунт пользователя истек срок действия, можно уведомить пользователя
if ($user->isExpired()) {
throw new AccountExpiredException('...');
}
}
}
Подключение пользовательской программы проверки пользователя
Далее, убедитесь в том, что ваша программа проверки пользователя зарегистрирована, как сервис. Если выиспользуете конфигурацию services.yml по умолчанию , то сервис регистрируется автоматически.
Всё, что остаётся сделать, это добавить программу проверки к желаемому брандмауэру, где значением будет id сервиса вашей программы проверки:
1 2 3 4 5 6 7 8 9
# config/packages/security.yaml
# ...
security:
firewalls:
main:
pattern: ^/
user_checker: App\Security\UserChecker
# ...
Использование нескольких программ проверки пользователя
Для приложений распространено иметь несколько точек входа аутентификации (таких как традиционная форма входа в систему и API), которые могут иметь уникальные правила программы проверки, а также общие правила для всех точек входа. Чтобы позволить использование нескольких программ проверки пользователей в брандмауэре, создается сервис для класса ChainUserChecker для каждого брандмауэра.
Чтобы использовать цепочку программ проверки пользователя, для начала вам нужно тегировать ваши
сервисы программы проверки пользователя тегом security.user_checker.<firewall>
(где <firewall>
- это имя брандмауэра в вашей конфигурации безопасности). Сервис-тег также поддерживает атрибут
приоритетности, что позволяет вам определять порядок, в котором вызываются ваши программы проверки
пользователя:
1 2 3 4 5 6 7 8 9 10 11 12
# config/services.yaml
# ...
services:
App\Security\AccountEnabledUserChecker:
tags:
- { name: security.user_checker.api, priority: 10 }
- { name: security.user_checker.main, priority: 10 }
App\Security\APIAccessAllowedUserChecker:
tags:
- { name: security.user_checker.api, priority: 5 }
Как только ваши сервисы программ проверки будут тегированы, далее вам нужно будет сконфигурировать
ваши брандмауэры, чтобы использовать сервис security.user_checker.chain.<firewall>
:
1 2 3 4 5 6 7 8 9 10 11 12 13
# config/packages/security.yaml
# ...
security:
firewalls:
api:
pattern: ^/api
user_checker: security.user_checker.chain.api
# ...
main:
pattern: ^/
user_checker: security.user_checker.chain.main
# ...