Брандмауэр и авторизация

Дата обновления перевода 2023-07-10

Брандмауэр и авторизация

Основным элементом компонента Security является авторизация. Она обрабатывается экземпляром AuthorizationCheckerInterface. Когда все шаги аутентификации пользователя были пройдены успешно, вы можете спросить проверщика авторизации, имеет ли аутентифицированній пользовательдоступ к определённому действию или источнику приложения:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
use Symfony\Component\Security\Core\Authorization\AuthorizationChecker;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;

// экземпляр Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface
$tokenStorage = ...;

// экземпляр Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface
$authenticationManager = ...;

// экземпляр Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface
$accessDecisionManager = ...;

$authorizationChecker = new AuthorizationChecker(
    $tokenStorage,
    $authenticationManager,
    $accessDecisionManager
);

// ... аутентифицировать пользователя

if (!$authorizationChecker->isGranted('ROLE_ADMIN')) {
    throw new AccessDeniedException();
}

Note

Прочтите соответствующие разделы, чтобы узнать больше о Аутентификация и Авторизация.

Брандмауэр для HTTP запросов

Аутентификация пользователя проводится брандмауэром. Приложение может иметь несколько безопасных областей, поэтому брандмауэр конфигурируется с использованием карты этих областей. Для каждой из них карта содержит сопоставитель запросов и набор слушателей. Сопоставитель запросов предоставляет брандмауэру возможность узавать, указывает ли текущий запрос на безопасную область. После этого слушателей спрашивают, может ли текущий запрос быть использован для аутентификации пользователя:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
use Symfony\Component\Security\Http\FirewallMap;
use Symfony\Component\HttpFoundation\RequestMatcher;
use Symfony\Component\Security\Http\Firewall\ExceptionListener;

$firewallMap = new FirewallMap();

$requestMatcher = new RequestMatcher('^/secured-area/');

// экземпляры Symfony\Component\Security\Http\Firewall\ListenerInterface
$listeners = array(...);

$exceptionListener = new ExceptionListener(...);

$firewallMap->add($requestMatcher, $listeners, $exceptionListener);

Карта брандмауэра будет передана брандмауэру в качестве его первого аргумента, вместе с диспетчером событий она будет использована классом HttpKernel:

1
2
3
4
5
6
7
8
9
10
11
12
use Symfony\Component\Security\Http\Firewall;
use Symfony\Component\HttpKernel\KernelEvents;

// EventDispatcher используемый HttpKernel
$dispatcher = ...;

$firewall = new Firewall($firewallMap, $dispatcher);

$dispatcher->addListener(
    KernelEvents::REQUEST,
    array($firewall, 'onKernelRequest')
);

Брандмауэр регистрируется для того, чтобы слушать событие kernel.request, которое будет запущено HttpKernel в начале каждого запроса, который он обрабатывает. Таким образом, брандмауэр может предотвратить пользователя от перехода дальше, чем ему позволено.

Конфигурация брандмауэра

Информация о заданном брандмауэре, вроде его имени, провайдера, контекста, точки входа и URL запрещённого доступа, предоставляется экземплярами класса FirewallConfig.

К этому объекту можно получить доступ через метод getFirewallConfig(Request $request) класса FirewallMap и через метод getConfig() класса FirewallContext.

Слушатели брандмауэра

Когда брандмауэр получает уведомление о событии kernel.request, он спрашивает карту брандмауэера, совпадает ли запрос с одной из безопасных областей. Первая безопасная область, которая совпадает с запросом, вернёт набор соответствующих слушателей брандмауэра (каждый из которых реализует ListenerInterface). Эти слушатели все будут обрабатывать текущий запрос. Это на самом деле означает: узнайте, содержит ли текущий запрос какую-либо информацию, по которой пользователь может быть аутентифицирован (например Базовый слушатель аутентификации HTTP проверяет, имеет ли запрос заголовок под названием PHP_AUTH_USER).

Слушатель исключений

Если любой из слушателей вызовет AuthenticationException, то слушатель исключений, который был предоставлен при добавлении безопасных областей в карту брандмауэра, начнёт свою работу.

Слущатель исключений определяет, что произойдет дальше, основываясь на аргументах, который он получил при создании. Он может начать процедуру аутентификации, возможно попросить пользователя повторно предоставить личные данные (если он был аутентифицирован только основываясь на куки "запомнить меня"), или преобразовать исключение в AccessDeniedHttpException, которое в итоге приведёт к ответу "HTTP/1.1 403: Отказ в доступе".

Точки входа

Если пользователь вообще не аутентифицирован (т.е. когда хранилище токенов ещё не имеет ни одного токена), точка входа брандмауэра будет вызвана для "запуска" процесса аутентификации. Точка входа должна релизовать AuthenticationEntryPointInterface, который имеет только один метод: start(). Этот метод получает текущий объект Request и исключение, по которому будет вызываться слушатель исключений. Метод также должен возвращать объект Response. Это может быть, к примеру, страница, содержащая форму входа, или в случае с базовой HTTP аутенификацией, ответ с заголовком WWW-Authenticate, который попросит пользователя предоставить его имя и пароль.

Процесс: Брандмауэр, Аутентификация, Авторизация

Надеемся, что теперь вы можете увидеть немного о том, как идёт "процесс" в контексте безопасности:

  1. Firewall регистрируется, как слушатель события kernel.request;
  2. В начале запроса, Firewall проверяет карту брандмауэра, чтобы увидеть, нужно ли активировать какой-либо из брандмауэров для этого URL;
  3. Если в карте для этого URL был найден брандмауэр, то уведомляются его слушатели;
  4. Каждый слушатель проверяет, содержит ли текущий запрос какую-либо информацию аутентификации - слушатель может (а) аутентифицировать пользователя, (б) вызвать AuthenticationException, или (в) ничего не делать (так как в запросе нет никакой информации аутентификации);
  5. Как только пользователь будет аутентифицирован, вы будете использовать Авторизация, чтобы отказать в доступе к определённым источникам.

Прочтите следующие разделы, чтобы узнать больше о Аутентификация и Авторизация.