- Безопасность¶
- 1) Установка¶
- 2a) Cоздайте ваш класс Пользователя¶
- 2b) “Поставщик пользователей”¶
- 2c) Хеширование паролей¶
- 3a) Аутентификация и файерволлы¶
- Как настроить вашу форму входа в систему¶
- Справочник конфигурации формы входа в систему¶
- Перенаправление после успеха¶
- Изменение страницы по умолчанию¶
- Авторизация¶
- Доступ к менеджеру решений¶
- Как построить традиционную форму входа в систему¶
- Перенаправление после успешного входа¶
- Избегайте распространённых ловушек¶
- 1. Создавайте правильные маршруты¶
- 2. Убедитесь, что страница входа не защищена (цикл перенаправления!)¶
- Авторизация и ограничение доступа в Symfony framework (Урок 14)
Безопасность¶
Система безопасности Symfony невероятно мощная, но в то же время может быть сложной в установке. Не волнуйтесь! В этой статье вы научитесь устанавливать безопасность вашего приложения шаг за шагом:
Несколько других важных тем обсуждаются после этого.
1) Установка¶
В приложениях, использующих Symfony Flex , выполните эту команду, чтобы установить функцию безопасности перед её использованием:
Новая экспериментальная Безопасность была представлена в Symfony 5.1, которая в итоге заменить безопасность в Symfony 6.0. Эта система почти полностью обратно совместима с текущей безопасностью Symfony, добавьте эту строку в вашу конфигруацию безопасности, чтобы начать ее использовать:
2a) Cоздайте ваш класс Пользователя¶
Независимо от того, как вы будете проводить аутентификацию (например, через форму входа в систему или API-токены), или где будут храниться ваши данные пользователя (база данных, единая точка входа), следующий шаг всегда будет одинаков: создание класса “Пользователя”. Самый простой способ — использовать MakerBundle.
Давайте предположим, что вы хотите хранить ваши данные пользователя в базе данных с Doctrine:
Вот и все! Команда задает несколько вопросов, чтобы сгенерировать именно то, что вам нужно. Наиболее важным является сам файл User.php . Единственное правило о вашем классе User — он должен реализовать UserInterface . Вы можете добавить любые другие поля или логику, которые вам нужны. Если ваш класс User является сущностью (как в этом примере), вы можете использовать команду make:entity , чтобы добавить больше полей. Также, убедитесь, что вы создали и запустили миграцию для новой сущности:
2b) “Поставщик пользователей”¶
В дополнение к вашему классу User , вам также нужен “Постащик пользователей”: класс, которые помогает с некоторыми вещами, вроде перезагрузки данных Пользоателя из сессии и некоторыми другими функциями, вроде запомнить меня и имперсонации .
К счастью, комагда make:user уже сконфигурировала его для вас в вашем файле security.yaml под ключом providers :
Если ваш класс User является сущностью, вам не нужно больше ничего делать. Но если ваш класс не сущность, то make:user также сгенерирует класс UserProvider , которые вам нужно закончить. Узнайте больше о поставщиках пользователей здесь: Поставщики пользователей .
2c) Хеширование паролей¶
Не все приложения имеют “пользователей”, которым нужны пароли. Если ваши пользователи имеют пароли, вы можете контролировать, как эти пароли хешируются в security.yaml . Команда make:user будет предварительно конфигурировать это для вас:
New in version 5.3: Опция password_hashers была представлена в Symfony 5.3. В предыдущих версиях она называлась encoders .
Теперь, когда Symfony знает, как вы хотите хешировать пароли, вы можете использовать сервис UserPasswordHasherInterface , чтобы сделать это перед сохранением ваших пользователей в базе данных.
К примеру, используя DoctrineFixturesBundle , вы можете создать фиктивных пользователей базы данных:
Используйте этот сервис для хеширования паролей:
Вы можете вручную хешировать пароль, выполнив:
3a) Аутентификация и файерволлы¶
New in version 5.1: Опция lazy: true была представлена в Symfony 5.1. До версии 5.1, она включалась с использованием anonymous: lazy
Система безопасности конфигурируется в config/packages/security.yaml . Наиболее важным разделом является firewalls :
“Файерволл” — это ваша система аутентификации: конфигурация под ней определяет то, как ваши пользователи будут аутентифицироваться (например, форма входа в систему, API-токен, и др.).
В каждом запросе активен только один файерволл: Symfony использует ключ pattern , чтобы найти первое совпадение (вы также можете сопоставлять с хостом или другими вещами ). Файерволл dev на самом деле фальшивый: он гарантирует, что вы случайно не заблокируете инструменты разработки Symfony — которые живут по URL вроде /_profiler и /_wdt .
Все настоящие URL обрабатываются главным файерволлом main (отсутствие ключа pattern означает, что он совпадает со всеми URL). Файерволл может иметь множество режимов аутентификации, другими словами, множество способов задавать вопрос “Кто вы?”. Часто, пользователь неизвествен (т.е. не выполнил вход в систему), когда пытается посетить ваш сайт. Режим anonymous , если он включен, используется для таких запросов.
На самом деле, если вы перейдете на домашнюю страницу праямо сейчас, вы будете иметь доступ и вы увидите, что вы “аутентифицированы” как anon. . Файерволл убедился, что не знает вашей личности и поэтому вы анонимны:
Это означает, что любой запрос может иметь токен анонимности для доступа к некоторым реусрками, в то время как некоторые действия (т.е. некоторые страницы или кнопки) все еще могут требовать конкретных привелегий. Пользователь может иметь доступ к форме входа в систему без аутентификации как уникальный пользоатель (другими словами, произойдет бесконечный цикл перенаправления, просящий пользователя пройти аутентификацию в то время, как он будет пытаться это сделать).
Вы позже узнаете, как отказывать в доступе к определенным URL, контроллерам или частям шаблонов.
Режим анонимности lazy предотвращает сессию от запуска, если нет необходимости для авторизации (т.е. ясной проверки привелегии пользователя). Это важно для того, чтобы запросы оставались кешируемыми (см; HTTP Cache ).
Если вы не видите панель инструментов, установите профилировщик с:
Источник
Как настроить вашу форму входа в систему¶
Использование формы входа в систему для аутентификации — это распространённый и гибкий метод для работы с аутентификацией в Symfony. В принципе, почти каждый аспект формы входа можно настроить. Полная конфигурация по умолчанию будет показана в следующем разделе.
Справочник конфигурации формы входа в систему¶
Чтобы увидеть полный справочник конфигурации формы входа, смотрите Security Configuration Reference (SecurityBundle) . Некоторые наиболее интересные опции раскрываются ниже.
Перенаправление после успеха¶
Вы можете изменить то, куда форма входа перенавпрялет после успешного входа в систему, используя разнообразные опции конфигурации. По умолчанию, форма будет перенаправлять на URL, запрошенный пользователем (т.е. URL, который вызвал отображение формы входа). Например, если пользователь запросил http://www.example.com/admin/post/18/edit , то после успешного входа в систему, он будет в итоге отправлен обратно на http://www.example.com/admin/post/18/edit . Это делается путём сохранения запрошенного URL в сессии. Если в сессии нет URL (возможно, пользователь сразу зашёл на страницу входа в систему), тогда пользователь будет перенаправлен на страницу по умолчанию — по умолчанию / (т.е. домашняя страница). Вы можете изменить это поведение несколькими путями.
Изменение страницы по умолчанию¶
Для начала, страница по умолчанию может быть установлена (т.е. страница, на которую перенаправляется ползователь, если в сессии не была сохранена предыдущая страница). Чтобы устноавить её в маршруте default_security_target , используйте следующую конфигурацию:
Источник
Авторизация¶
Когда любой из поставщикой аутентификации (см. Поставщики аутентификации ) подтвердил все-еще-неавторизованный токен, будет возващён аутентифицированный токен. Слушатель аутентификации установит этот токен напрямую в TokenStorageInterface , используя его метод setToken() .
С этого момента пользователь будет аутентифицирован, т.е. идентифицирован. Теперь, другие части приложения могут использовать токен, чтобы решить, может ли пользователь запрашивать определённый URI или изменять определённый объект. Это решение будет принято экземпляром AccessDecisionManagerInterface .
Решение авторизации будет всегда основываться на нескольких вещах:
- Текущем токене Например, метод токена getRoleNames() может быть использован для извлечения ролей текущего пользователя (например, ROLE_SUPER_ADMIN ), или решение может быть основано на классе токена.
- Наборе атрибутов Каждый атрибут представляет определённое право, которое должен иметь пользователь, к примеру ROLE_ADMIN , чтобы гарантировать, что пользователь является администратором.
- Объекте (опционально) Любой объект, для которого нужно проверять контроль доступа, вроде объекта статьи или комментария.
Доступ к менеджеру решений¶
Так как принятие решения о том, авторизирован ли пользователь производить определённое действие, может быть достаточно сложным процессом, сам стандартный AccessDecisionManager зависит от нескольких избирателей и выносит финальный вердикт, основываясь на всех голосах (положительных, отрицательных или нейтральных), который он получил. Он признаёт несколько стратегий:
affirmative (по умолчанию) предоставлять доступ, как только есть один избиратель, предоставляющий доступ; consensus предоставлять доступ, если больше избирателей предоставляют доступ, чем отказывают в нём; unanimous предоставлять доступ только, если ни один из избирателей не отказал в нём. Если все избиратели воздержались от голосования, решение основывает на опции конфигурации allow_if_all_abstain (по умолчанию false ). priority
предоставляет или отказывает в доступе первому избирателю, который не воздреживается;
New in version 5.1: Версия стратегии priority была представлена в Symfony 5.1.
Источник
Как построить традиционную форму входа в систему¶
Если вам нужна форма входа, и вы храните пользователей в какой-то DB, то вам стоит рассмотреть использование FOSUserBundle, который помогает вам строить ваш объект User и предоставляет множество маршрутов и контроллеров для общих задач вроде выполнения входа, регистрации и забытого пароля.
В этой записи вы построите традиционную форму входа в систему. Конечно, когда пользователь выполняет вход, вы можете загружать ваших пользователей откуда угодно — например, из DB. Смотрите, 2b) The “User Provider” , чтобы узнать больше.
Для начала, включите форму входа в систему под вашим брандмауэром:
login_path и check_path также могут быть именами маршрута (но не не могут иметь обязательные подстановочные знаки — например, /login/
Теперь, когда система безопасности инициирует процесс аутентификации, она будет перенаправлять пользователя на форму выполнения входа /login . Реализация этой формы входа в систему — ваша работа. Для начала, создайте новый SecurityController внутри пакета:
Далее, сконфигурируйте маршрут, который вы ранее использовали в вашей конфигурации form_login ( login ):
Отлично! Далее, добавьте логику к loginAction() , которая отображает форму входа:
Не дайте этому контроллеру смутить вас. Как вы увидите через секунду, когда пользователь отпарвляет форму, система безопасносати автоматически обрабатывает отправку формы для вас. Если пользователь отправляет недействительное имя пользователя или пароль, контроллер считывает ошибку отправки формы из системы безопасности, чтобы позже отобразить её пользователю.
Другими словами, ваша работа — отобразить форму входа и любые ошибки входа, которые могли возникнуть, но система безопасности сама заботится о проверке отправленных имени пользователя и пароля, а также об аутентификации пользователя.
Finally, create the template:
Переменная error передаётся в шаблон, как экземпляр AuthenticationException . Он может содержать болше информации — даже секретной — об ошибке аутентификации, так что используйте его с умом!
Форма может выглядеть как угодно, но обычно она следует некоторым договорённостям:
- Элемент отправляет запрос POST к маршруту login ,так как это то, что вы сконфигурировали под ключом form_login в security.yml ;
- Поле имени пользователя имеет имя _username , а поле пароля — _password .
На самом деле, всё это можно сконфигурировать под ключом form_login . Смотрите form_login Authentication , чтобы узнать больше.
Эта форма входа в систему на данный момент не защищена от CSRF-атак. Прочтите /security/csrf_in_login_form , чтобы узнать, как защитить вашу форму.
Вот и всё! Когда вы отправляете форму, система безопамности автоматически проверит аккредитацию пользователя и либо аутентифицирует его, либо отправит пользователя обратно к форме входа, где будет отображена ошибка.
Повторим весь процесс:
- Пользователь пытается получить доступ к защищённому ресурсу;
- Брандмауэр инициирует процесс аутентификации, перенаправляя пользователя к форме входа в систему ( /login );
- Страница /login отображает форму входа через маршрут и контроллер, созданные в этом примере;
- Пользователь отправляет форму входа в /login ;
- Система безопасности принимает запрос, проверяет отправленную пользователем аккредитацию, аутентифицирует пользователя, если всё верно, и отправляет пользователя обратно к форме входа — если нет.
Перенаправление после успешного входа¶
Если отправленная аккредитация верна, пользователь будет перенаправлен на страницу, которая была запрошена первоначально (например, /admin/foo ). Если пользователь изначально зашёл на страницу входа в систему, он будет перенаправлен на домашнюю страницу. Это можно настроить, и вы можете, например, перенаправить пользователя по конкретному URL.
Чтобы узнать больше деталей об этом и о том, как настроить процесс формы входа в систему в общем, смотрите Using the form_login Authentication Provider .
Избегайте распространённых ловушек¶
При установке вашей формы входа в систему, будьте осторожны с наиболее распространёнными ловушками.
1. Создавайте правильные маршруты¶
Во-первых, убедитесь, что вы правильно определили маршрут /login , и что он соответствует значениям конфигурации login_path и check_path . Неправильная конфигурация тут может означать, что вы будете перенаправлены на страницу 404 вместо страницы входа, или что отправка формы входа ничего не будет делать (вы просто будете видеть форму входа снова и снова).
2. Убедитесь, что страница входа не защищена (цикл перенаправления!)¶
Также, убедитесь в том, что страница входа доступна анонимным пользователям. Например, следующая конфигурация, требующая роль ROLE_ADMIN для всех URL (включая URL /login ), будет вызывать цикл перенаправления:
Источник
Авторизация и ограничение доступа в Symfony framework (Урок 14)
Итак, в этой заметке мы научимся ограничивать доступ к разделам сайта, написанного с использованием Symfony framework. Symfony framework предоставляет мощные средства для контроля доступа, которые позволяют ограничивать доступ как по url, так и целым контроллерам.
Если вы путаетесь в понятиях аутентификация, идентификация и авторизация, советую для начала прочитать это.
Сначала немного теории.
То, что нам необходимо, делается с помощью конфигурационного файла (yaml по умолчанию, app/config/security.yml).
Когда пользователь делает запрос до защищенного с помощью firewall url, активируется система защиты.
Система сначала определяет, нужна ли аутентификация, если да — тогда возвращает ответ пользователю, инициирующий процесс аутентификации. После введения данных проверяется наличие пользователя, его права, и, если их достаточно, возвращается изначально запрашиваемая страница.
Информация о пользователях может находится как в конфигурационном файле (app/config/security.yml) (если у вас 1-2 пользователя, включая админа — сойдет =)) или в базе данных (если у вас сложная многопользовательская система).
Рассмотрим базовый пример:
В секции firewalls мы указали, что система защиты активируется для всех входящих запросов, (pattern задает шаблон url`ов), также в следующей строке мы открыли доступ для неавторизированных пользователей.
Параметры form_login login_path и check_path указывают роуты для формы авторизации и проверки данных (Форма — обычный action контроллера, login_check action в простейшем случае описывать не понадобится).
В следующей секции, access_control, мы снова задали шаблон url, но уже для защищенной части ресурса, и указали, какие типы («роли» в терминах Symfony framework) пользователей имеют доступ к защищенной части.
Следующая секция позволяет указать источники учетных данных пользователей. У примере — прямо в конфигурационном файле. Учтите, что если пароль начинается из цифр, его нужно взять в кавычки. Так же учтите, что получив доступ к конфигурационному файлу, сторонние лица могут легко узнать ваш пароль.
Для отображения логин формы, необходимо создать для нее роутинг. Например, так:
И сам action контроллера (взят с официального руководства по Symfony framework):
Итак, мы научились ограничивать доступ к разделам проекта, написанного на Symfony framework с помощью конфигурационных файлов. Список пользователей сохраняется в этих же файлах. В следующих заметках научимся, как задействовать для этого БД.
Источник