Як створити користувацького постачальника користувачів
Дата оновлення перекладу 2023-06-23
Як створити користувацького постачальника користувачів
Частина стандартного процесу аутентифікації Symfony залежить від "постачальників
користувачів". Коли користувач надсилає ім'я користувача та пароль, шар
аутентифікації просить сконфігурованого постачальника користувачів повернути об'єкт
користувача для даного імені користувача. Потім Symfony перевіряє, чи правильний
пароль у цього користувача і генерує токен безпеки, щоб користувач залишався у системі
під час поточної сесії. Одразу після встановлення, Symfony має чотири постачальники користувачів:
memory
, entity
, ldap
та chain
. В цій статті ви побачите, як ви можете створити
власного постачальника користувачів, який може бути корисним, якщо доступ до ваших користувачів
отримано через користувацьку DB, файл, або, як показано в цьому прикладі, через веб-сервіс.
Створіть клас користувача
Для початку, незалежно від того, звідки йдуть дані користувача, вам
знадобиться створити клас User
, який представляє ці дані. User
може виглядати так, як вам цього хочеться, і містити будь-які дані.
Єдина вимога - щоб він реалізовував
UserInterface.
Методи в цьому інтерфейсі тому мають бути визначені у користувацькому класі користувача
getRoles(),
getPassword(),
getSalt(),
getUsername(),
eraseCredentials().
Також може бути корисно реалізувати інтерфейс
EquatableInterface, який
визначає метод для перевірки, чи дорівнює користувач поточному користувачеві. Цей
інтерфейс вимагає методу isEqualTo().
Ось як ваш клас WebserviceUser
виглядає в дії:
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
// src/Security/User/WebserviceUser.php
namespace App\Security\User;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\EquatableInterface;
class WebserviceUser implements UserInterface, EquatableInterface
{
private $username;
private $password;
private $salt;
private $roles;
public function __construct($username, $password, $salt, array $roles)
{
$this->username = $username;
$this->password = $password;
$this->salt = $salt;
$this->roles = $roles;
}
public function getRoles()
{
return $this->roles;
}
public function getPassword()
{
return $this->password;
}
public function getSalt()
{
return $this->salt;
}
public function getUsername()
{
return $this->username;
}
public function eraseCredentials()
{
}
public function isEqualTo(UserInterface $user)
{
if (!$user instanceof WebserviceUser) {
return false;
}
if ($this->password !== $user->getPassword()) {
return false;
}
if ($this->salt !== $user->getSalt()) {
return false;
}
if ($this->username !== $user->getUsername()) {
return false;
}
return true;
}
}
Якщо у вас є більше інформації про ваших користувачів, наприклад, "ім'я",
тоді ви можете додати поле firstName
для зберігання цих даних.
Створіть постачальника користувачів
Тепер, коли у вас є клас User
, ви створите постачальника користувачів,
який буде брати інформацію про користувача з якогось веб-сервісу, створювати
об'єкт WebserviceUser
і наповнюватиме його даними.
Постачальник користувачів - це простий PHP-клас, який має реалізувати
UserProviderInterface,
який вимагає визначення трьох методів: loadUserByUsername($username)
,
refreshUser(UserInterface $user)
, і supportsClass($class)
. Щоб
дізнатися більше деталей, дивіться
UserProviderInterface.
Ось приклад того, як це може виглядати:
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
// src/Security/User/WebserviceUserProvider.php
namespace App\Security\User;
use App\Security\User\WebserviceUser;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
class WebserviceUserProvider implements UserProviderInterface
{
public function loadUserByUsername($username)
{
// тут зробіть виклик до вашого веб-сервісу
$userData = ...
// уявіть, що він повертає масив за умови вдалої операції, і false, якщо користувача немає
if ($userData) {
$password = '...';
// ...
return new WebserviceUser($username, $password, $salt, $roles);
}
throw new UsernameNotFoundException(
sprintf('Username "%s" does not exist.', $username)
);
}
public function refreshUser(UserInterface $user)
{
if (!$user instanceof WebserviceUser) {
throw new UnsupportedUserException(
sprintf('Instances of "%s" are not supported.', get_class($user))
);
}
return $this->loadUserByUsername($user->getUsername());
}
public function supportsClass($class)
{
return WebserviceUser::class === $class;
}
}
Створіть сервіс для постачальника користувачів
Тепер ви зробите постачальника користувачів доступним як сервіс. Якщо ви використовуєте конфігурацію services.yaml за замовчуванням , це відбудеться автоматично.
Налаштування security.yaml
Все сходиться разом у вашій конфігурації безпеки. Додайте постачальника користувачів
до списку постачальників у конфігурації безпеки. Виберіть ім'я для постачальника користувачів
(наприклад, "webservice") і вкажіть id
сервісу, який ви щойно визначили.
1 2 3 4 5 6 7
# config/packages/security.yaml
security:
# ...
providers:
webservice:
id: App\Security\User\WebserviceUserProvider
Symfony також повинна знати, як шифрувати паролі, які поставляються користувачами сайту, наприклад, заповнюючи форму входу в систему. Ви можете зробити це, додавши рядок до розділу "кодувальники" у вашій конфігурації безпеки:
1 2 3 4 5 6
# config/packages/security.yaml
security:
# ...
encoders:
App\Security\User\WebserviceUser: bcrypt
Значення тут має співпадати з тим, як спочатку були зашифровані
паролі при створенні ваших користувачів (і тим, як були створені користувачі).
Коли користувач надсилає свій пароль, він зашифровується з використанням
цього алгоритму і результат порівнюється з хешованим паролем, повернутим
методом getPassword()
.