Регистрацию и авторизацию будем делать с помощью прекрасного бандла — FosUserBudle. Его многие не любят, говорят, что он костыльный и плохо работает, но для блога, как по мне, самое оно. В следующем проекте мы напишем свои модули регистрации и авторизация с нуля, а сейчас — приступим.
У бандла есть документация, но она для Symfony 3.4. Поэтому в процессе некоторые шаги я буду адаптировать под нашу новенькую Symfony 4.
Сначала устанавливаем сам бандл:
1
|
composer require friendsofsymfony/user—bundle
|
Теперь удостоверься, что в файле config\bundles.php в самом конце появилась строчка:
1
|
FOS\UserBundle\FOSUserBundle::class => [‘all’ => true]
|
Если нет — добавь, сохраняй и идём дальше.
Теперь нам нужно импортировать все маршруты, которые определены в FosUserBundle. Помнишь, мы разбирали с тобой тему маршрутизации? Так вот маршруты, помимо аннотаций над контроллерами, можно определять в специальном конфиге — config/routes/fos_user.yaml. Помимо определения маршруты можно импортировать из конфигов, где они уже определены. Открывай вышеназванный конфиг и добавляй туда следующее:
1
2
|
fos_user:
resource: «@FOSUserBundle/Resources/config/routing/all.xml»
|
Если перейти в конфиг, из которого мы производим импорт, то можно обнаружить, что и в этом файле происходит импорт:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
<?xml version=«1.0» encoding=«UTF-8» ?>
<routes xmlns=«http://symfony.com/schema/routing»
xmlns:xsi=«http://www.w3.org/2001/XMLSchema-instance»
xsi:schemaLocation=«http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd»>
<import
resource=«@FOSUserBundle/Resources/config/routing/security.xml» />
<import
resource=«@FOSUserBundle/Resources/config/routing/profile.xml»
prefix=«/profile» />
<import
resource=«@FOSUserBundle/Resources/config/routing/registration.xml»
prefix=«/register» />
<import
resource=«@FOSUserBundle/Resources/config/routing/resetting.xml»
prefix=«/resetting» />
<import
resource=«@FOSUserBundle/Resources/config/routing/change_password.xml»
prefix=«/profile» />
</routes>
|
Синтаксис XML мы не разбирали, но интуитивно он понятен, только лишь чуть сложнее yaml. Если перейдёшь дальше, то увидишь маршруты, которые будут импортированы в наше приложение.
Дальше нужно явно сообщить Symfony, что возможные шаблонизаторы в нашем приложении — это twig и php. Открывай файл config\packages\framework.yaml и сразу после framework: перед secret:.. добавляй:
1
2
|
templating:
engines: [‘twig’, ‘php’]
|
Чтобы ты не запутался, получится должно так:
Дальше открывай файл config\packages\security.yaml и меняй его конфигурацию на следующую:
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
|
security:
encoders:
App\Entity\User: bcrypt
role_hierarchy:
ROLE_ADMIN: ROLE_USER
ROLE_SUPER_ADMIN: ROLE_ADMIN
providers:
fos_userbundle:
id: fos_user.user_provider.username
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
anonymous: true
logout: ~
logout_on_user_change: true
form_login:
csrf_token_generator: security.csrf.token_manager
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 }
|
Теперь разбор того, что добавилось.
1
2
|
encoders:
App\Entity\User: bcrypt
|
Устанавливает алгоритм шифрования для полей, хранящих пароли в указанной сущности — App\Entity\User. Bcrypt — это функция, позволяющая шифровать данные и хранить их в защищённом виде.
Далее:
1
2
3
|
role_hierarchy:
ROLE_ADMIN: ROLE_USER
ROLE_SUPER_ADMIN: ROLE_ADMIN
|
Иерархия ролей. К этой теме мы вернёмся чуть попозже и подробно её разберём, сейчас лишь скажу, что в Symfony есть система ролей — пользователи, админы, анонимы и так далее. Можно создавать новые роли и кастомизировать их. В нашем случае у нас две роли — ROLE_USER и ROLE_ADMIN, которые мы, грубо говоря, по-другому назвали — название (алиас) и стоит в качестве ключа.
1
2
3
|
providers:
fos_userbundle:
id: fos_user.user_provider.username
|
Провайдер — это та вещь, которая возвращает необходимые данные по некоторым известным данным пользователя. Мы используем провайдер, предоставленный FosUserBundl’ом.
1
2
3
4
5
6
|
main:
anonymous: true
logout: ~
logout_on_user_change: true
form_login:
csrf_token_generator: security.csrf.token_manager
|
Firewall — система защиты. Мы объявляем файрвол с именем main, и указываем для него:
anonymous: true — анонимы могут видеть форму авторизации и регистрации (насколько я понимаю)
logout: ~ — тильда означает null. Иначе говоря, разлогиниваться без повода мы не будем.
logout_on_user_change: true -если пользователь изменился, старый будет разлогиниваться. Касается устройства, с которого сидит пользователь.
form_login:
csrf_token_generator: security.csrf.token_manager — генератор токенов — ключей текущей сессии пользователя. К ним мы вернёмся, когда будем писать свои модули регистрации и авторизации.
Секция access_control задаёт уровень доступа к роутам. Админка (мы её установили в одном из предыдущих уроков) — только для админов. Регистрация, авторизация и восстановление пароля — для всех, включая самый низкий уровень — анонимный пользователь.
Далее в директории packages проверь, есть ли файл fos_user.yaml. Если нет — создавай, если да — открывай, а потом пиши:
1
2
3
4
5
6
7
|
fos_user:
db_driver: orm
firewall_name: main
user_class: App\Entity\User
from_email:
sender_name: «Jun Senior»
|
Этот файл задаёт основные настройки для бандла.
db_driver : orm, потому что у нас ООП-слой над реляционной БД.
firewall_name : main, мы его только что создали.
user_class : App\Entity\User.
from_email — задавай свои. Эти данные будут подставляться в письма пользователю, когда ему на почту будет приходить подтверждение регистрации или письмо со сменой пароля.
А дальше нам нужно создать сущность пользователя. Бандл уже имеет базовую сущность User, где прописаны все основные поля — логин, почта, пароль, etc. Нам остаётся только создать свою сущность User с единственным переопределённым, на текущий момент, полем — id, и унаследовать её от сущности из бандла. Тем самым мы унаследуем все основные поля и методы, а в свой дочерний класс будем дописывать только нужные нам. Создавай в директории Entity файл User.php, а затем вставляй в него следующий код:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
<?php
namespace App\Entity;
use FOS\UserBundle\Model\User as BaseUser;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
* @ORM\Table(name=»fos_user»)
*/
class User extends BaseUser
{
/**
* @ORM\Id
* @ORM\Column(type=»integer»)
* @ORM\GeneratedValue(strategy=»AUTO»)
*/
protected $id;
public function __construct()
{
parent::__construct();
// your own logic
}
}
|
Заметь, что наш namespace отличается от namespace из мана, линк на который я оставил выше. Стандартный namespace в Symfony4 — это App\*, а не BundleName\*, как это было в 3.4.
Класс наследуется от сущности User, определённой в Fos\UserBundle\Model\User. Если открыть файл User, который располагается по пути vendor/friendsofsymfony/user-bundle/Model/, то увидишь поля и методы, которые мы унаследовали:
Теперь обновляем схему, чтобы ORM создала таблицу по нашему, только что созданному, классу:
1
|
php bin/console doctrine:schema:update —force
|
Так, ну вроде бы всё. Теперь в браузере переходи страницу /login и наблюдай:
Да, детка. Это страница авторизации.
Теперь перейди по пути /register:
А это страница регистрации. Всё отлично, всё на месте. Теперь вводи данные и нажимай кнопку Register:
Теперь через консоль выдадим пользователю права супер-админа. Как? С помощью команд, которые нам предоставляет бандл.
1
|
php bin/console fos:user:promote testuser —super
|
Вместо testuser подставь тот логин, который ты указал при регистрации.
Тебе должен придти подобный ответ:
1
|
User «junsenior» has been promoted as a super administrator. This change will not apply until the user logs out and back in again.
|
Теперь нажимаем Log out:
И входим заново. Переходим на страницу /admin и видим:
Да есть же — юзер на месте, прямиком в табличке fos_user. Поздравляю, так как нам открылась страница /admin, то мы успешно стали администратором и теперь можем авторизироваться, регистрироваться, выходить и входить.
В одной из следующих статей (может в следующий вторник) я покажу тебе, как сделать восстановление пароля, как кастомизировать админку, как сделать ajax-регистрацию и авторизацию (у меня просили бахнуть ajax — получите), и в конце концом как кастомизировать эти отвратительные страницы с голой разметкой в нечто красивое и радующее глаз.