Постачальники користувачів
Дата оновлення перекладу 2024-06-03
Постачальники користувачів
Постачальники користувачів (повторно) завантажують користувачів зі сховища (наприклад, бази даних), засновуючись на "ідентифікаторі користвача" (наприклад, адресі електронної пошти або імені користувача). Див. , щоб дізнатися більше про те, коли використовується постачальник користувачів.
Symfony надає декілька постачальників користувачів:
- Постачальник користувачів сутності
- Завантажує користувачів з бази даних, використовуючи Doctrine;
- Постачальник користувачів LDAP
- Завантажує постачальників з сервера LDAP;
- Постачальник користувачів памʼяті
- Завантажує користувачів з файлу конфігурації;
- Ланцюговий постачальник користувачів
- Зливае два або більше постачальників користувачів у нового постачальника користувачів.
Постачальник користувачів сутності
Цей найрозповсюдженіший постачальник користувачів. Користувачі зберігаються у базі даних, а постачальник використовує Doctrine, щоб вилучити їх:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
# config/packages/security.yaml
security:
providers:
users:
entity:
# клас сутності, який представляє користувачів
class: 'App\Entity\User'
# властивість для запиту - наприклад, імʼя користувача, електронна пошта і т.д.
property: 'email'
# необовʼязково: якщо ви використовуєте декілька менеджерів сутностей Doctrine,
# ця опція визначає, якого використовувати
#manager_name: 'customer'
# ...
Використання користувацького запиту для завантаження користувача
Постачальник сутностей може робити запит лише з одного конкретного поля, вказаного ключем
конфігурації property
. Якщо ви хочете мати трохи більше контролю - наприклад, ви хочете
знайти користувача за email
або username
, ви можете зробити це, реалізувавши
UserLoaderInterface у вашому
сховищі Doctrine (наприклад, UserRepository
):
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
// src/Repository/UserRepository.php
namespace App\Repository;
use App\Entity\User;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Symfony\Bridge\Doctrine\Security\User\UserLoaderInterface;
class UserRepository extends ServiceEntityRepository implements UserLoaderInterface
{
// ...
public function loadUserByIdentifier(string $usernameOrEmail): ?User
{
$entityManager = $this->getEntityManager();
return $entityManager->createQuery(
'SELECT u
FROM App\Entity\User u
WHERE u.username = :query
OR u.email = :query'
)
->setParameter('query', $usernameOrEmail)
->getOneOrNullResult();
}
}
Щоб закінчити, видаліть ключ property
з постачальника користувачів у
security.yaml
:
1 2 3 4 5 6 7 8
# config/packages/security.yaml
security:
providers:
users:
entity:
class: App\Entity\User
# ...
Тепер, кожний раз, коли Symfony використовуватиме постачальника користувачів, у вашому
UserRepository
буде викликано метод loadUserByIdentifier()
.
Постачальник користувачів памʼяті
Не рекомендовано використовувати цього постачальника у реальних додатках через його обмеження і те, наскільки складно управляти користувачами. Він може бути корисним у прототипах додатків та для обмежених додатків, які не зберігають користувачів у базах даних.
Цей постачальник користувачів зберігає всю інформацію користувачів у файлі конфігурації, включно з паролями. Переконайтеся в тому, що пароли правильно хешовані. Див. Хешування та верифікація паролів, щоб дізнатися більше.
Після налаштування хешування, ви можете сконфігурувати всю користувацьку інформацію
в security.yaml
:
1 2 3 4 5 6 7 8 9 10
# config/packages/security.yaml
security:
providers:
backend_users:
memory:
users:
john_admin: { password: '$2y$13$jxGxc ... IuqDju', roles: ['ROLE_ADMIN'] }
jane_admin: { password: '$2y$13$PFi1I ... rGwXCZ', roles: ['ROLE_ADMIN', 'ROLE_SUPER_ADMIN'] }
# ...
Caution
При використанні постачальника memory
, а не алгоритму auto
, вам потрібно
обирати алгоритм хешування без солі (тобто, bcrypt
).
Ланцюговий постачальник користувачів
Цей постачальник користувачів обʼєднує два або більше інших типів постачальників користувачів
(entity
і ldap
), щоб створити нового постачальника користувачів. Порядок, в якому
сконфігуровані постачальники, важливий, так як Symfony шукатиме користувачів з першого постачальника
і продовжуватиме шукати їх в інших постачальниках, поки не знайде:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
# config/packages/security.yaml
security:
# ...
providers:
backend_users:
ldap:
# ...
legacy_users:
entity:
# ...
users:
entity:
# ...
all_users:
chain:
providers: ['legacy_users', 'users', 'backend_users']
Створення користувацького постачальника користувачів
Більшість додатків не вимагають створення користувацького постачальника. Якщо ви зберігаєте користувачів у базі даних, на LDAP-сервері або у файлі конфігурації, Symfony це підтримує. Однак, якщо ви завантажуєте користувачів з користувацького місця (наприклад, через API або успадковані зʼєднання бази даних), вам знадобиться створити корситувацького постачальника користувачів.
Спочатку, переконайтеся, що ви дотримувалися Посібника з Безпеки при
створенні вашого класу User
.
Якщо ви використали команду make:user
для створення вашого класу User
(і ви відповіли
на запитання, що вказують, що вам необхідний користувацький постачальник), то ця команда
згенерує гарний скелет для того, щоб почати:
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
// src/Security/UserProvider.php
namespace App\Security;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
use Symfony\Component\Security\Core\Exception\UserNotFoundException;
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
use Symfony\Component\Security\Core\User\PasswordUpgraderInterface;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
class UserProvider implements UserProviderInterface, PasswordUpgraderInterface
{
/**
* Метод loadUserByIdentifier() було представлено в Symfony 5.3.
* У попередніх версіях він називався loadUserByUsername()
*
* Symfony викликає цей метод, якщо ви використовуєте функції на кшталт switch_user
* або remember_me. Якщо ви не використовуєте ці функції, вам не потрібно реалізовувати
* цей метод.
*
* @throws UserNotFoundException, якщо користувача не знайдено
*/
public function loadUserByIdentifier(string $identifier): UserInterface
{
// Завантажити обʼєкт User з вашого джерела даних або викликати UserNotFoundException.
// Аргумент $identifier - те значення, яке повертається методом
// getUserIdentifier() у вашому класі User.
throw new \Exception('TODO: fill in loadUserByIdentifier() inside '.__FILE__);
}
/**
* Оновлює користувача після повторного завантаження з сесії.
*
* Коли користувач увійшов у систему, на початку кожного запиту, обʼєкт
* User завантажується з сесії, а потім викликається цей метод. Ваша задача
* - переконатисяс, що дані користувача все ще свіжі, шляхом, наприклад, повторного
* запиту свіжих даних користувача.
*
* Якщо ваш брандмауер "stateless: true" (для чистого API), цей метод
* не викликається.
*
* @return UserInterface
*/
public function refreshUser(UserInterface $user)
{
if (!$user instanceof User) {
throw new UnsupportedUserException(sprintf('Invalid user class "%s".', get_class($user)));
}
// Повернути обʼєкт User післе того, як переконалися. що його дані "свіжі".
// Або викликати UserNotFoundException, якщо користувач вже не існує.
throw new \Exception('TODO: fill in refreshUser() inside '.__FILE__);
}
/**
* Вказує Symfony використати цього постачальника для цього класу User.
*/
public function supportsClass(string $class)
{
return User::class === $class || is_subclass_of($class, User::class);
}
/**
* Оновлює зашифрований пароль користувача, зазвичай для використання кращого алгоритму хешування.
*/
public function upgradePassword(UserInterface $user, string $newEncodedPassword): void
{
// ЗРОБИТИ: коли використовуються хешовані паролі, цей метод повинен:
// 1. зберігати новий пароль у сховище користувача
// 2. оновлювати обʼєкт $user з $user->setPassword($newHashedPassword);
}
}
Більшість роботи вже зроблена! Прочитайте коментарі у коді та оновіть розділи
ЗРОБИТИ, щоб закінчити з постачальником користувачів. Коли ви завершите, повідомте
Symfony про постачальника користувачів, додавши його у security.yaml
:
1 2 3 4 5 6
# config/packages/security.yaml
security:
providers:
# the name of your user provider can be anything
your_custom_user_provider:
id: App\Security\UserProvider
Нарешті, оновіть файл config/packages/security.yaml
, щоб встановити ключ
provider
як your_custom_user_provider
у всіх брандмауерах, які будуть
використовувати цього користувацького постачальника.