Реализуйте свой собственный SecurityController
Недавно я написал статью для своей компании об управлении пользователями и их аутентификации изначально с помощью Symfony2 Core и, следовательно, без FOSUserBundle. Вслед за этой и без того насыщенной первой статьей я хотел описать вторую, не менее полезную часть, которая позволит нам быстро настроить необходимые функции, а именно сброс пароля, изменение пароля, подтверждение аккаунта или даже регистрацию. Действия столь же важны, когда у вас есть система, управляющая пользователями.
Настроить SecurityController
Во-первых, если вы не следовали первому туториалу о том, как настроить управление пользователями, советую вам взглянуть. Если вы следовали решению, логически у вас должен быть SecurityController или что-то еще. В моем случае у меня есть только три метода, и только один из них действительно применим.
- вход в систему
Этот метод подключает пользователя. - checkAction
Этот метод просто позволяет вам объявить маршрут для брандмауэра, позволяя пользователю подключаться на стороне сервера. - logoutAction
Этот метод используется для объявления маршрута для брандмауэра, позволяющего отключить пользователя.
Откройте нашу платформу для новых пользователей
Было бы особенно интересно, если бы наши пользователи могли подключиться и, следовательно, зарегистрироваться заранее.
Во-первых, мы создаем форму с информацией, которую вы хотите запросить у пользователя.
Что касается формы, которую вы будете использовать для регистрации вашего пользователя, знай, что поле» password не должно быть в вашей форме. Однако вам нужно будет добавить два поля " не нанесен на карту чтобы дважды ввести желаемый пароль.
1
2
3
4
5
6
7
8
9
10
11
12
13
|
/ **
* @Метод({"ПОЛУЧАТЬ"})
* @Маршрут(«/ зарегистрироваться», имя = «зарегистрироваться»)
* @Безопасный(роли = «IS_AUTHENTICATED_ANONYMOUSLY»)
* @Шаблон()
*/
что такое варган? функция зарегистрироваться()
{
$ форма = $ Этой-> создать форму (new Тип пользователя(Тип пользователя::РЕГИСТРАЦИЯ), new Пользователь());
возвращение массив(
"форма" => $form->createView(),
);
}
|
Затем, когда ваш пользователь вернется с заполненной формой, нам придется зарегистрировать его или отклонить его файл: p
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
29
30
|
/ **
* @Метод({"ПОЧТА"})
* @Маршрут("/регистр")
* @Безопасный(роли = «IS_AUTHENTICATED_ANONYMOUSLY»)
* @Шаблон()
*/
что такое варган? функция зарегистрироваться(Запрос $ запрос)
{
$params = $запрос->запрос->все()[«имя_моей_формы»];
$ форма = $ Этой-> создать форму (new Тип пользователя(Тип пользователя::РЕГИСТРАЦИЯ), new Пользователь());
$ форма-> отправить ($ запрос);
if (ключ_массива_существует(«простой_пароль», $params) && array_key_exists("простой_пароль2", $params) && $params[«простой_пароль»] == $параметры["простой_пароль2"]) {
if ($ форма->действительно()) {
$данные = $form->getData();
$ данные-> установить пароль ($ Этой->контейнер->получить(«security.encoder_factory»)->getEncoder($data)->encodePassword($params[«простой_пароль»], $data->getSalt()));
$em->сохранить($данные);
$em->смыть();
возвращение $ Этой-> перенаправить ($ Этой-> сгенерировать URL-адрес ("авторизоваться", массив(" сообщение " => «Вы получили электронное письмо для подтверждения вашей учетной записи. »)));
}
}
возвращение массив(
«ошибки» => $ параметры[«простой_пароль»] == $параметры["простой_пароль2"]? $форма->получитьОшибки(): массив(«Два пароля должны быть одинаковыми»),
"форма" => $form->createView(),
);
}
|
Здесь мы быстро детализируем рабочий для регистрации нового пользователя.
- Мы смотрим если все обязательные поля заполнены правильно, включая два поля «пароль», и если последние два идентичны.
- Кодируем пароль и мы «устанавливаем» его в объекте.
- В случае какой-либо ошибки мы возвращаем форму с ошибкой, которая, по нашему мнению, должна быть подробно описана.
Создайте функцию для сброса пароля
Теперь ваш пользователь может войти в систему, но что мы будем делать, если он потеряет свой пароль. Очевидно, что мы не собираемся создавать контактный адрес электронной почты, посвященный его бесполезным операциям.
Как вы видели выше, я обычно объявляю два метода для каждой из моих функций: один из моих методов отвечает за управление представлением, созданным по запросу. ПОЛУЧИТЬ и результат запроса POST. Вы можете абсолютно объединить эти два метода в один и тот же метод.
1
2
3
4
5
6
7
8
9
|
/ **
* @Метод({"ПОЛУЧАТЬ"})
* @Маршрут(«/сброс», имя = «сброс»)
* @Безопасный(роли = «IS_AUTHENTICATED_ANONYMOUSLY»)
* @Шаблон()
*/
что такое варган? функция сброс() {
возвращение массив();
}
|
На втором этапе мы объявим дополнительный метод, управляющий запросами. POST.
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
29
|
/ **
* @Метод({"ПОЧТА"})
* @Маршрут("/перезагрузить")
* @Безопасный(роли = «IS_AUTHENTICATED_ANONYMOUSLY»)
*/
что такое варган? функция сбросить сейчас(Запрос $ запрос)
{
$params = $запрос->запрос->все();
if (!array_key_exists("авторизоваться", $параметры)) {
бросать new Исключение(«Логин не указан»);
}
$ логин = & $ параметры ["авторизоваться"];
$эм = $ Этой->контейнер->получить(«doctrine.orm.default_entity_manager»);
$user = $em->getRepository(«NamespaceMyBundle: Пользователь»)->найтиOneBy(массив("авторизоваться" => $логин));
if ($ пользователь == нуль) {
возвращение $ Этой-> перенаправить ($ Этой-> сгенерировать URL-адрес ("авторизоваться", массив()));
}
$ пароль = «мой случайный пароль»;
$ пользователь-> установить пароль ($ Этой->контейнер->получить(«security.encoder_factory»)->getEncoder($user)->encodePassword($password, $user->getSalt()));
$em->persist($user);
$em->смыть();
// Отправляем пароль по электронной почте
возвращение $ Этой-> перенаправить ($ Этой-> сгенерировать URL-адрес ("авторизоваться", массив()));
}
|
Этот метод был разработан для укрыватель преступника пароль пользователя, предоставившего свой логин/имя пользователя. В моем случае пароль был отправлен по электронной почте. Я позволю тебе добавить эту галантную строчку.
- Итак, мы собираемся поиск пользователя.
- Генерируем пароль что мы пришли сообщить пользователю после того, как он закодировал в соответствии с правилами, которые вы определили.
Настроить смену пароля
На этом этапе наш пользователь может сгенерировать новый пароль, если он был утерян, но в случае, если он просто хочет его изменить, нам нужен шлюз для определения шлюза.
1
2
3
4
5
6
7
8
9
|
/ **
* @Метод({"ПОЛУЧАТЬ"})
* @Маршрут(«/ изменить», имя = «изменить пароль»)
* @Безопасный(роли = «IS_AUTHENTICATED_FULLY»)
* @Шаблон()
*/
что такое варган? функция изменение() {
возвращение массив();
}
|
Вот код для создания представления. Сначала вам нужно будет ввести свой старый пароль, а затем дважды ввести новый пароль. Второй раз подтверждение.
Теперь мы увидим код для восстановитель пароль. НАШИ процесс подготовки аналогично генерации нового случайного пароля.
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
29
30
31
32
33
34
35
36
37
38
|
/ **
* @Метод({"ПОЧТА"})
* @Маршрут("/изменять")
* @Безопасный(роли = «IS_AUTHENTICATED_FULLY»)
* @Шаблон()
*/
что такое варган? функция изменитьСейчас(Запрос $ запрос)
{
$params = $запрос->запрос->все();
if (!array_key_exists("текущий", $параметры)
|| !array_key_exists("новый", $параметры)
|| !array_key_exists(«новый2», $параметры))
{
возвращение массив("Ошибка" => "Пожалуйста заполните все поля");
}
$эм = $ Этой->контейнер->получить(«doctrine.orm.default_entity_manager»);
$пользователь= $ Этой->получитьпользователя();
$user_encoders = $ Этой->контейнер->получить(«security.encoder_factory»)->getEncoder($user);
$user_repository = $em->getRepository(«NamespaceMyBundle: Пользователь»);
$current_password_encoded = $user_encoders->encodePassword($params["текущий"], $user->getSalt());
$new_password_encoded = $user_encoders->encodePassword($params["новый"], $user->getSalt());
if ($user_repository->findOneBy(массив("пароль" => $current_password_encoded)) == нуль) {
возвращение массив("Ошибка" => «Текущий пароль неверный»);
} ElseIf ($ параметры["новый"] != $параметры[«новый2»]) {
возвращение массив("Ошибка" => "Пароли двух полей не совпадают");
}
$user->setPassword($new_password_encoded);
$em->persist($user);
$em->смыть();
возвращение $ Этой-> перенаправить ($ Этой-> сгенерировать URL-адрес ("выйти", массив()));
}
|
Если вы потратите 1 минуту на чтение кода, вы увидите, что он особенно прост.
- Сначала мы проверяем правильность ввода трех полей (старый пароль, новый пароль и подтверждение).
- On введите пароль текущий и мы сравниваем его с текущим паролемв базе данных, чтобы увидеть, соответствует ли он введенному старому паролю.
- Проверяем, есть ли "два" новых пароля идентичный.
- Введите новый пароль и push в сущности.
Активация его аккаунта
Эта функция не полностью детализирована в других обрывки выше. Его цель — разблокировать пользователя, который только что зарегистрировался, когда он, например, подтвердил свою электронную почту. Этот функционал разработан практически на всех известных нам платформах по нескольким причинам. Чтобы настроить блокировку пользователя, вам также может понадобиться реализовать провайдер.
- блок/лимит аккаунтов не настоящие и спам.
- Контрольник что пользователь ввел адрес электронной почты, который на первый взгляд кажется пригодным для использования.
- Удалять учетные записи, которые не были проверены по истечении определенного периода времени.
Рабочий процесс
- Пользователь регистрируется. Затем его учетная запись блокируется с помощью определенного для вас поля. Это поле должно препятствовать его подключению до тех пор, пока это поле указывает, что учетная запись отключена.
1
2
3
4
5
6
7
8
|
// Пространство именMyBundleEntityUser
класс Информация о пользователе {
что такое варган? функция __конструкт() {
$ Этой->token = хэш(«ша512», уникальный());
}
...
}
|
1
|
$пользователь->setEnabled(ложный);
|
- Пользователь получил электронное письмо, когда его профиль был промыватель в базе данных. Это электронное письмо должно быть частью созданного вами адреса.
На этой дороге а token или уникальный идентификатор, позволяющий найти соответствующего пользователя. Я советую вам использовать UUID4, который должен быть случайным. Вы можете найти список UUID, а также описание всех версий.
1
2
3
4
|
/ **
* @Маршрут(«/активировать», имя = «активировать»)
*/
что такое варган? функция активировать() {…}
|
1
|
$ Этой-> сгенерировать URL-адрес («активировать», массив(« token » => $пользователь->получитьToken()), правда);
|
У вас должен быть такой URL.
1
|
HTTP://имя хоста/активировать?token=мойУникальныйToken
|
- Пользователь открывает свою электронную почту и пытается активировать свою учетную запись, нажав на предоставленную ссылку. Затем мы вступаем в процесс ниже.
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
|
/ **
* @Метод({"ПОЛУЧАТЬ"})
* @Маршрут(«/активировать», имя = «активировать»)
* @Безопасный(роли = «IS_AUTHENTICATED_ANONYMOUSLY»)
* @Шаблон()
*/
что такое варган? функция активировать(Запрос $ запрос) {
$ параметры = массив();
$token = $запрос->запрос->получить(« token »);
$эм = $ Этой->контейнер->получить(«doctrine.orm.default_entity_manager»);
$user = $em->getRepository(«NamespaceMyBundle: Пользователь»)->найтиOneBy(массив(« token » => $token));
if ($пользователь != нуль) {
$пользователь->setEnabled(правда);
$em->persist($user);
$em->смыть();
$ параметры [«активировать»знак равно правда;
} еще {
$ параметры [«активировать»знак равно ложный;
}
возвращение $ параметры;
}
|
С этим процессом у вас не должно возникнуть проблем с включением проверки учетной записи пользователя.
Вы можете найти этот эквивалентный код в этом Gist.
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
|
использование JMSБезопасностьаннотированиеБезопасно;
использование SensioПакетFrameworkExtraBundleКонфигурацияСпособ доставки;
использование SensioПакетFrameworkExtraBundleКонфигурациядорога;
использование SensioПакетFrameworkExtraBundleКонфигурацияшаблон;
использование SymfonyПакетFrameworkBundleконтроллерконтроллер;
использование SymfonyКомпонентHttpFoundationЗапрос;
использование SymfonyКомпонентБезопасностьОсновныеSecurityContext;
класс Контроллер безопасности продолжается контроллер
{
/ **
* @Метод({"ПОЛУЧАТЬ"})
* @Маршрут(«/логин», имя = «логин»)
* @Шаблон()
*/
что такое варган? функция Войти(Запрос $ запрос)
{
$ запрос = $ Этой->ПолучитьЗапрос();
$session = $request->getSession();
if ($request->attributes->has(SecurityContext::AUTHENTICATION_ERROR)) {
$error = $request->attributes->get(SecurityContext::AUTHENTICATION_ERROR);
} еще {
$error = $session->get(SecurityContext::AUTHENTICATION_ERROR);
$session->remove(SecurityContext::AUTHENTICATION_ERROR);
}
$ параметры = массив(
«последнее_имя_пользователя» => $session->get(SecurityContext::LAST_USERNAME),
"Ошибка" => $ ошибка,
" сообщение " => $запрос->получить(" сообщение "),
);
if ($запрос->isXmlHttpRequest()) {
возвращение $ Этой->рендерить(«GCDirectoryMainBundle:Security:login-ajax.html.twig», $параметры);
}
возвращение $ параметры;
}
/ **
* @Метод({"ПОЧТА"})
* @Маршрут(«/login_check», имя = «login_check»)
*/
что такое варган? функция проверка()
{
бросать new RuntimeException («Вы должны настроить путь проверки для обработки брандмауэром, используя form_login в конфигурации вашего брандмауэра безопасности».);
}
/ **
* @Метод({"ПОЛУЧАТЬ"})
* @Маршрут(«/выйти», имя = «выйти»)
*/
что такое варган? функция Выход()
{
бросать new RuntimeException («Вы должны активировать выход из системы в настройках брандмауэра безопасности».);
}
/ **
* @Метод({"ПОЛУЧАТЬ"})
* @Маршрут(«/сброс», имя = «сброс»)
* @Безопасный(роли = «IS_AUTHENTICATED_ANONYMOUSLY»)
* @Шаблон()
*/
что такое варган? функция сброс() {
возвращение массив();
}
/ **
* @Метод({"ПОЧТА"})
* @Маршрут("/перезагрузить")
* @Безопасный(роли = «IS_AUTHENTICATED_ANONYMOUSLY»)
*/
что такое варган? функция сбросить сейчас(Запрос $ запрос)
{
$params = $запрос->запрос->все();
if (!array_key_exists("авторизоваться", $параметры)) {
бросать new Исключение(«Логин не указан»);
}
$ логин = & $ параметры ["авторизоваться"];
$эм = $ Этой->контейнер->получить(«doctrine.orm.default_entity_manager»);
$user = $em->getRepository(«NamespaceMyBundle: Пользователь»)->найтиOneBy(массив("авторизоваться" => $логин));
if ($ пользователь == нуль) {
возвращение $ Этой-> перенаправить ($ Этой-> сгенерировать URL-адрес ("авторизоваться", массив()));
}
$ пароль = «мой случайный пароль»;
$ пользователь-> установить пароль ($ Этой->контейнер->получить(«security.encoder_factory»)->getEncoder($user)->encodePassword($password, $user->getSalt()));
$em->persist($user);
$em->смыть();
возвращение $ Этой-> перенаправить ($ Этой-> сгенерировать URL-адрес ("авторизоваться", массив()));
}
/ **
* @Метод({"ПОЛУЧАТЬ"})
* @Маршрут(«/ изменить», имя = «изменить пароль»)
* @Безопасный(роли = «IS_AUTHENTICATED_FULLY»)
* @Шаблон()
*/
что такое варган? функция изменение() {
возвращение массив();
}
/ **
* @Метод({"ПОЧТА"})
* @Маршрут("/изменять")
* @Безопасный(роли = «IS_AUTHENTICATED_FULLY»)
* @Шаблон()
*/
что такое варган? функция изменитьСейчас(Запрос $ запрос)
{
$params = $запрос->запрос->все();
if (!array_key_exists("текущий", $параметры)
|| !array_key_exists("новый", $параметры)
|| !array_key_exists(«новый2», $параметры))
{
возвращение массив("Ошибка" => "Пожалуйста заполните все поля");
}
$эм = $ Этой->контейнер->получить(«doctrine.orm.default_entity_manager»);
$пользователь= $ Этой->получитьпользователя();
$user_encoders = $ Этой->контейнер->получить(«security.encoder_factory»)->getEncoder($user);
$user_repository = $em->getRepository(«NamespaceMyBundle: Пользователь»);
$current_password_encoded = $user_encoders->encodePassword($params["текущий"], $user->getSalt());
$new_password_encoded = $user_encoders->encodePassword($params["новый"], $user->getSalt());
if ($user_repository->findOneBy(массив("пароль" => $current_password_encoded)) == нуль) {
возвращение массив("Ошибка" => «Текущий пароль неверный»);
} ElseIf ($ параметры["новый"] != $параметры[«новый2»]) {
возвращение массив("Ошибка" => "Пароли двух полей не совпадают");
}
$user->setPassword($new_password_encoded);
$em->persist($user);
$em->смыть();
возвращение $ Этой-> перенаправить ($ Этой-> сгенерировать URL-адрес ("выйти", массив()));
}
/ **
* @Метод({"ПОЛУЧАТЬ"})
* @Маршрут(«/ зарегистрироваться», имя = «зарегистрироваться»)
* @Безопасный(роли = «IS_AUTHENTICATED_ANONYMOUSLY»)
* @Шаблон()
*/
что такое варган? функция зарегистрироваться()
{
$ форма = $ Этой-> создать форму (new Тип пользователя(Тип пользователя::РЕГИСТРАЦИЯ), new Пользователь());
возвращение массив(
"форма" => $form->createView(),
);
}
/ **
* @Метод({"ПОЧТА"})
* @Маршрут("/регистр")
* @Безопасный(роли = «IS_AUTHENTICATED_ANONYMOUSLY»)
* @Шаблон()
*/
что такое варган? функция зарегистрироваться(Запрос $ запрос)
{
$params = $запрос->запрос->все()[«имя_моей_формы»];
$ форма = $ Этой-> создать форму (new Тип пользователя(Тип пользователя::РЕГИСТРАЦИЯ), new Пользователь());
$ форма-> отправить ($ запрос);
if (ключ_массива_существует(«простой_пароль», $params) && array_key_exists("простой_пароль2", $params) && $params[«простой_пароль»] == $параметры["простой_пароль2"]) {
if ($ форма->действительно()) {
$данные = $form->getData();
$ данные-> установить пароль ($ Этой->контейнер->получить(«security.encoder_factory»)->getEncoder($data)->encodePassword($params[«простой_пароль»], $data->getSalt()));
$em->сохранить($данные);
$em->смыть();
возвращение $ Этой-> перенаправить ($ Этой-> сгенерировать URL-адрес ("авторизоваться", массив(" сообщение " => «Вы получили электронное письмо для подтверждения вашей учетной записи. »)));
}
}
возвращение массив(
«ошибки» => $ параметры[«простой_пароль»] == $параметры["простой_пароль2"]? $форма->получитьОшибки(): массив(«Два пароля должны быть одинаковыми»),
"форма" => $form->createView(),
);
}
/ **
* @Метод({"ПОЛУЧАТЬ"})
* @Маршрут(«/активировать», имя = «активировать»)
* @Безопасный(роли = «IS_AUTHENTICATED_ANONYMOUSLY»)
* @Шаблон()
*/
что такое варган? функция активировать(Запрос $ запрос) {
$ параметры = массив();
$token = $запрос->запрос->получить(« token »);
$эм = $ Этой->контейнер->получить(«doctrine.orm.default_entity_manager»);
$user = $em->getRepository(«NamespaceMyBundle: Пользователь»)->найтиOneBy(массив(« token » => $token));
if ($пользователь != нуль) {
$user->setActive(User::ACTIVE_ACTIVE);
$em->persist($user);
$em->смыть();
$ параметры [«активировать»знак равно правда;
} еще {
$ параметры [«активировать»знак равно ложный;
}
возвращение $ параметры;
}
}
|