Symfony имеет очень мощную систему аутентификации и авторизации, которая может удовлетворить многие наши потребности из коробки. FOSUserBundle — это библиотека, построенная поверх системы безопасности Symfony, которая обеспечивает такие функции, как регистрация, вход в систему, сброс пароля и т. Д. Она имеет встроенную поддержку MongoDB, а также ORM, такие как Doctrine, Propel и т. Д.
Мы будем использовать 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/
, мы должны увидеть такую регистрационную форму.
Настройка шаблонов
Теперь у нас есть работающая, но базовая система регистрации пользователей и входа в систему. Форма выглядит слишком наивной для использования в любых реальных проектах. Далее мы увидим, как мы можем настроить шаблоны, чтобы они выглядели лучше.
Мощная система шаблонов 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
отобразит сообщение об ошибке для соответствующего поля.
Мы можем настроить все другие шаблоны, чтобы соответствовать остальной части приложения.
Аналогично, если мы хотим настроить метки и другие сообщения, мы можем скопировать каталог 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 . Дайте нам знать, если у вас есть какие-либо вопросы или комментарии!