Статьи

Основное управление пользователями в Symfony2 с помощью FOSUserBundle

Symfony имеет очень мощную систему аутентификации и авторизации, которая может удовлетворить многие наши потребности из коробки. FOSUserBundle — это библиотека, построенная поверх системы безопасности Symfony, которая обеспечивает такие функции, как регистрация, вход в систему, сброс пароля и т. Д. Она имеет встроенную поддержку MongoDB, а также ORM, такие как Doctrine, Propel и т. Д.

Users networked graphic

Мы будем использовать Homestead Improved для нашей демонстрации.

Давайте добавим новый сайт в файл Homestead.yml .

 sites: - map: symfonylogin.app to: /home/vagrant/Code/SymfonyLogin/web type: symfony databases: - symfony 

Это создаст новый сайт в виртуальной машине, который будет указывать на web папку приложения Symfony. Когда указан type: symfony , он выберет конфигурацию Nginx, специально созданную для приложений Symfony.

Мы также должны добавить 192.168.10.10 symfonylogin.app в файл /etc/hosts основной операционной системы. Теперь мы можем загрузить виртуальную vagrant up с vagrant up .

Прежде чем мы начнем, давайте быстро настроим приложение Symfony с помощью установщика Symfony, инструмента командной строки для установки проектов Symfony. Чтобы установить установщик, мы входим в виртуальную vagrant ssh с помощью vagrant ssh и запускаем следующие команды.

 curl -LsS http://symfony.com/installer > symfony sudo mv symfony /usr/local/bin/symfony chmod a+x /usr/local/bin/symfony 

Первая команда загружает установщик с веб-сайта Symfony в текущий каталог. Затем мы перемещаем его в каталог bin и делаем его исполняемым.

Теперь давайте создадим приложение Symfony внутри виртуальной машины.

 cd Code symfony new SymfonyLogin 

Это создаст скелетное приложение Symfony и установит все зависимости от Packagist. По завершении мы можем перейти в папку app/config и обновить файл parameters.yml со значениями нашей базы данных и конфигурации электронной почты.

Теперь мы можем открыть http://symfonylogin.app в браузере, чтобы увидеть запущенное приложение скелета.

Symfony ограничивает доступ среды разработки к IP 127.0.0.1 . При использовании Vagrant вам может потребоваться обновить файл app_dev.php чтобы добавить IP-адрес вашего хоста в список.

Основное использование

FOSUserBundle может быть легко подключен к проектам Symfony с минимальными изменениями конфигурации и кода. Давайте посмотрим, как мы можем сделать это в нашем.

Установка комплекта

Сначала мы установим пакет:

 composer require friendsofsymfony/user-bundle "~2.0@dev" 

конфигурация

Прежде чем мы сможем использовать FOSUserBundle, мы должны зарегистрировать пакет в AppKernel.

 class AppKernel extends Kernel { public function registerBundles() { $bundles = array( ... new FOS\UserBundle\FOSUserBundle(), ); ... return $bundles; } 

FOSUserBundle использует компонент перевода Symfony для отображения меток форм и ошибок. По умолчанию он отключен в конфигурации, и нам нужно внести следующие изменения в config.yml .

 translator: { fallbacks: ["%locale%"] } 

Теперь давайте настроим безопасность в security.yml .

 security: encoders: AppBundle\Entity\User: bcrypt role_hierarchy: ROLE_ADMIN: ROLE_USER ROLE_SUPER_ADMIN: ROLE_ADMIN providers: fos_userbundle: id: fos_user.user_provider.username firewalls: main: pattern: ^/ form_login: provider: fos_userbundle csrf_provider: security.csrf.token_manager logout: true anonymous: true access_control: - { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY } - { path: ^/register, role: IS_AUTHENTICATED_ANONYMOUSLY } - { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY } - { path: ^/admin/, role: ROLE_ADMIN } 

Компонент безопасности Symfony предоставляет несколько параметров конфигурации, которые позволят нам настроить практически каждый аспект. Здесь мы указали единственные параметры, которые нам нужно изменить, и оставили все остальное в значении по умолчанию. Посмотрим, что мы изменили.

 encoders: AppBundle\Entity\User: bcrypt 

encoders сообщат приложению, какой алгоритм использовать для кодирования паролей для объекта User. Это наш класс сущности User, который мы создадим на следующих шагах.

 providers: fos_userbundle: id: fos_user.user_provider.username 

Это зарегистрирует провайдера пользователя, где fos_user.user_provider.username — это идентификатор службы FOS\UserBundle\Security\UserProvider зарегистрированной в FOS User Bundle.

firewalls в Symfony аналогичны межсетевым экранам, с которыми мы знакомы. Мы создали один межсетевой экран с именем main . Ключ pattern определяет шаблоны URL, которым должен соответствовать этот межсетевой экран. Ключ form_login указывает, что мы будем использовать форму входа для аутентификации пользователей, и мы хотим использовать наш fos_userbundle в качестве поставщика пользователя.

access_control ограничивает доступ к URL-адресам на основе пользовательских ролей. Страницы входа в систему, регистрации и сброса должны быть общедоступными, поэтому им требуется роль IS_AUTHENTICATED_ANONYMOUSLY , которая по умолчанию предоставляется любому, кто получает доступ к любой странице.

Пользовательский класс

FOSUserBundle требует от нас создания объекта User, который необходимо сохранить в базе данных. Пакет уже предоставляет абстрактный базовый класс с большинством необходимых нам полей. Нам просто нужно создать сущность, которая расширяет этот базовый класс.

 <?php // src/AppBundle/Entity/User.php namespace AppBundle\Entity; use FOS\UserBundle\Model\User as BaseUser; use Doctrine\ORM\Mapping as ORM; /** * User * * @ORM\Table("fos_user") * @ORM\Entity */ class User extends BaseUser { /** * @var integer * * @ORM\Column(name="id", type="integer") * @ORM\Id * @ORM\GeneratedValue(strategy="AUTO") */ protected $id; /** * Get id * * @return integer */ public function getId() { return $this->id; } } 

Базовый класс не имеет поля идентификатора, поэтому мы должны иметь его в нашей сущности вместе с любыми другими полями, которые нам нужны для нашего приложения.

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

 fos_user: db_driver: orm firewall_name: main user_class: AppBundle\Entity\User 

db_driver : orm использовать Doctrine.

firewall_name : main указывает имя брандмауэра для использования.

user_class: AppBundle\Entity\User сообщает приложению, что мы хотим использовать AppBundle\Entity\User в качестве класса пользователя.

Обновить схему

Создав Entity, мы также можем сгенерировать пользовательскую таблицу, используя CLI Symfony.

 php app/console doctrine:schema:update --force 

Это создаст таблицу с именем fos_user в нашей базе данных, с полями, доступными из FOSUserBundle. Если вам нужны какие-либо дополнительные поля, вы можете указать их в сущности Пользователь, прежде чем создавать схему.

Импортные маршруты

Symfony не импортирует маршруты поставщиков самостоятельно. Вместо этого нам нужно вручную добавить их в app/config/routing.yml .

 fos_user: resource: "@FOSUserBundle/Resources/config/routing/all.xml" 

Это импортирует все маршруты, доступные в FOSUserBundle .

Теперь, когда мы настроили пакет и настроили все, мы можем проверить, работает ли он. Если мы перейдем по http://symfonylogin.app/register/ , мы должны увидеть такую ​​регистрационную форму.

Registration form

Настройка шаблонов

Теперь у нас есть работающая, но базовая система регистрации пользователей и входа в систему. Форма выглядит слишком наивной для использования в любых реальных проектах. Далее мы увидим, как мы можем настроить шаблоны, чтобы они выглядели лучше.

Мощная система шаблонов Symfony позволяет нам легко расширять и переопределять шаблоны, которые идут в комплекте. Чтобы переопределить шаблоны пакета, мы должны создать каталог в app/Resources и присвоить ему имя пакета. Затем мы создаем каталог представлений и размещаем там все шаблоны, которые переопределяют.

Если мы проверим местоположение vendor/friendsofsymfony/user-bundle/Resources/views , мы найдем все шаблоны, используемые FOSUserBundle. Нам нужно создать структуру FOSUserBundle/views/ в app/Resources/ и поместить туда файлы наших шаблонов. Давайте скопируем каталог Registration из FOSUserBundle в это место. Теперь наш каталог app/Resources должен выглядеть примерно так.

 // ProjectRoot/app/Resources ├── FOSUserBundle │ └── views │ └── Registration │ ├── checkEmail.html.twig │ ├── confirmed.html.twig │ ├── email.txt.twig │ ├── register.html.twig │ └── register_content.html.twig └── views ├── base.html.twig └── default └── index.html.twig 

Теперь мы можем обновить register.html.twig с нашими требованиями.

 {% extends "base.html.twig" %} {% block body %} <div class="row"> <div class="col s12 m8 offset-m2"> <h4 class="card-panel teal lighten-2 white-head">Signup</h4> </div> </div> <div class="row"> <div class="col s12 m8 offset-m2"> {% include "FOSUserBundle:Registration:register_content.html.twig" %} </div> </div> {% endblock body %} 

Здесь я предполагаю, что у вас уже есть файл макета base.html.twig для вашего приложения с содержимым тела, отображаемым в блоке body .

Мы также изменим register_content.html.twig чтобы мы могли отображать элементы формы по своему желанию.

 {% trans_default_domain 'FOSUserBundle' %} {{form_start(form, {'method': 'POST', 'attr':{'class': 'register'}})}} <div class="row"> <div class="input-field col s12"> {{ form_label(form.username) }} {{ form_widget(form.username) }} </div> {{ form_errors(form.username) }} </div> <div class="row no-padding"> <div class="input-field col s12"> {{ form_label(form.email) }} {{ form_widget(form.email) }} </div> {{ form_errors(form.email) }} </div> <div class="row no-padding"> <div class="input-field col s12"> {{ form_label(form.plainPassword.first) }} {{ form_widget(form.plainPassword.first) }} </div> {{ form_errors(form.plainPassword.first) }} </div> <div class="row no-padding"> <div class="input-field col s12"> {{ form_label(form.plainPassword.second) }} {{ form_widget(form.plainPassword.second) }} </div> {{ form_errors(form.plainPassword.second) }} </div> <div align="center" class="button-wrap"> <button class="btn-large waves-effect waves-light" type="submit" name="action"> {{ 'registration.submit'|trans }} <i class="material-icons">send</i> </button> </div> {{ form_end(form) }} 

form_start откроет тег формы с заданными атрибутами, а form_end закроет эту форму. Если мы проверим фактический шаблон, мы увидим только {{ form_widget(form) }} , который будет отображать всю форму. Но так как нам нужны наши собственные стили для элементов формы, мы визуализируем отдельные элементы формы, используя form_label и form_widget . Если какой-либо элемент не проходит проверку при form_errors формы, form_errors отобразит сообщение об ошибке для соответствующего поля.

RegistrationForm updated

Мы можем настроить все другие шаблоны, чтобы соответствовать остальной части приложения.
Аналогично, если мы хотим настроить метки и другие сообщения, мы можем скопировать каталог translations из FOSUserBundle и поместить его в наш каталог app/Resources/FOSUserBundle . Затем мы редактируем FOSUserBundle.en.yml и меняем любые нужные нам значения.

Подтверждение Регистрации

В большинстве случаев нам необходимо подтвердить свой адрес электронной почты перед завершением процесса регистрации. Это легко сделать, обновив конфигурацию config.yml в config.yml . Теперь это должно выглядеть примерно так.

 fos_user: db_driver: orm firewall_name: main user_class: AppBundle\Entity\User from_email: address: [email protected] sender_name: Example.com registration: confirmation: enabled: true template: FOSUserBundle:Registration:email.txt.twig 

Обратите внимание на новый registration ключ, который мы добавили здесь. enabled: true для confirmation включит процесс подтверждения, и мы используем FOSUserBundle:Registration:email.txt.twig шаблон для содержимого электронной почты.

Также обратите внимание на from_email ключ from_email . Он сообщит пакету об использовании этого письма в качестве адреса отправителя для всех отправляемых нами писем.

Теперь пользователи, пытающиеся зарегистрироваться, получат подтверждение по электронной почте со ссылкой для подтверждения своего адреса электронной почты.

Для отправки сообщений электронной почты от Symfony убедитесь, что у вас есть работающая конфигурация smtp в файле parameters.yml .

Авторизоваться

До сих пор мы видели, как настроить форму регистрации и настроить шаблоны. Вход в систему не требует дополнительной настройки, встроенного функционала достаточно для любого приложения. Если мы перейдем к http://symfonylogin.app/login , мы увидим форму входа. Если мы уже вошли в систему, мы также увидим ссылку выхода из системы в шаблоне по умолчанию.

Система безопасности Symfony перехватывает отправку формы входа и пытается аутентифицировать пользователя, используя провайдера аутентификации, который мы указали в конфигурации безопасности. Большая часть этого выполняется самим компонентом безопасности Symfony, описанным здесь .

Забыл пароль

FOSUserBundle также предоставляет возможность сброса пароля. Пользователи могут перейти по http://symfonylogin.app/resetting/request и предоставить свое имя пользователя или адрес электронной почты для сброса пароля. Если этот пользователь существует, приложение отправит электронное письмо на зарегистрированный адрес электронной почты.

Профиль пользователя

FOSUserBundle поставляется с базовой страницей профиля. После входа в систему, если мы перейдем по адресу http://symfonylogin.app/profile/ , мы увидим страницу профиля по умолчанию. Конечно, эту страницу также необходимо настроить для использования в любых нестандартных проектах.

 {% trans_default_domain 'FOSUserBundle' %} {% extends "base.html.twig" %} {% block body %} <div class="fos_user_user_show"> <p>{{ 'profile.show.username'|trans }}: {{ user.username }}</p> <p>{{ 'profile.show.email'|trans }}: {{ user.email }}</p> </div> <a href="{{ path('fos_user_profile_edit') }}">Edit Profile</a> {% endblock body %} 

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

Мы также можем обновить профиль со страницы редактирования профиля ( http://symfonylogin.app/profile/edit ). Для дополнительной безопасности пользователь должен предоставить текущий пароль для обновления профиля.

Резюме

FOSUserBundle — это плагин для регистрации пользователей и управления ими в приложениях Symfony. Построенный на основе системы безопасности Symfony, этот пакет заботится о большей, если не о всей сложности безопасности Symfony при реализации регистрации пользователя и входа в систему.

Для получения дополнительной информации, ознакомьтесь с обширной документацией, чтобы узнать больше об этом комплекте.

Код для этого урока доступен на Github . Дайте нам знать, если у вас есть какие-либо вопросы или комментарии!