Аутентификация через объекты Pimcore
Поскольку компонент безопасности Symfony достаточно сложен, Pimcore предоставляет базовые реализации для упрощения интеграции конфигурации безопасности с пользователями, хранящимися в виде объектов Pimcore.
В качестве примера предположим, что у нас есть объект пользователя, определенный в классе App\Model\DataObject\User, который хранит пароль в поле с именем password (тип поля Password). Поле пароля настроено на использование алгоритма password_hash, который в наши дни является стандартным способом обработки паролей в PHP (внутренне он использует bcrypt). Определение класса выглядит следующим образом (вы можете найти рабочий пример в установочном профиле demo-basic):

Поскольку объект пользователя должен реализовывать интерфейс UserInterfaceот Symfony, нам необходимо переопределить сгенерированный класс и реализовать методы, которые отсутствуют в стандартных геттерах полей:
<?php
// src/Model/DataObject/User.php
namespace App\Model\DataObject;
use Pimcore\Model\DataObject\ClassDefinition\Data\Password;
use Pimcore\Model\DataObject\User as BaseUser;
use Symfony\Component\Security\Core\User\UserInterface;
/**
* Наш кастомный класс пользователя, реализующий Symfony UserInterface.
*/
class User extends BaseUser implements UserInterface
{
/**
* Метод для удаления открытого пароля из экземпляра класса.
*
* Это необходимо, чтобы открытые пароли не попали в сериализованные данные.
*/
public function eraseCredentials(): void
{
/** @var Password $field */
$field = $this->getClass()->getFieldDefinition('password');
$field->getDataForResource($this->getPassword(), $this);
}
}
Затем настроим Pimcore на использование нашего переопределенного класса:
# config/config.yaml
pimcore:
models:
class_overrides:
'Pimcore\Model\DataObject\User': 'App\Model\DataObject\User'
Загрузка пользователей через User Provider
Провайдер пользователей отвечает за поиск объекта пользователя по заданному логину. Pimcore предоставляет ObjectUserProvider, который загружает пользователей из объекта определенного класса и ищет в указанном поле. В нашем случае мы хотим загрузить пользователей из App\Model\DataObject\User и запросить поле username. Чтобы иметь возможность использовать наш пользовательский класс в конфигурации безопасности, мы определяем сервис поставщика услуг, который настроен для загрузки нашей пользовательской реализации (убедитесь, что ваш пакет может загружать определения сервисов, см. загрузка определений сервисов):
# config/services.yaml
services:
# Провайдер загружает пользователей по Username.
# Pimcore предоставляет простой ObjectUserProvider, который может загружать пользователей из указанного класса с помощью настроенного
# поля. website_demo.security.user_provider будет загружать пользователей из the App\Model\DataObject\User, просматривая их
# поле username.
website_demo.security.user_provider:
class: Pimcore\Security\User\ObjectUserProvider
arguments: ['App\Model\DataObject\User', 'username']
Мы будем использовать эту службу позже в нашей конфигурации безопасности, чтобы указать брандмауэру, откуда загружать своих пользователей. Для получения более подробной информации взгляните на ObjectUserProvider который в основном вызывает User::getByUsername($username, 1) внутренне. Если у вас есть
более сложные варианты использования, вы можете расширить ObjectUserProvider или предоставить свою полностью настраиваемую реализацию.
Дополнительные сведения см. в разделе Как создать провайдера пользователей документации Symfony.
Хеширование паролей
Стандартный подход к хешированию и проверке пароля пользователя в Symfony заключается в делегировании логики PasswordHasherInterface
который отвечает за вычисление и проверку хэшей паролей. Поскольку определение поля Password в Pimcore уже предоставляет
эту логику, необходимо настроить хэшер паролей для делегирования логики объекту пользователя.
Symfony builds and caches one password hasher instance per user type (class). To be able to delegate the calculation to the user object it is necessary to build an password hasher instance which is scoped to the user object and can access the user's properties at runtime. Pimcore adds this as additional layer of configuration which allows to specify a password hasher factory per user type which in turn can decide if it needs to build dedicated instances of password hashers per user.
Symfony создает и кэширует один экземпляр password hasher для каждого типа пользователя (класса). Чтобы иметь возможность делегировать вычисление объекту пользователя, необходимо создать экземпляр password hasher, который привязан к объекту пользователя и может получать доступ к свойствам пользователя во время выполнения. Pimcore добавляет это в качестве дополнительного уровня настройки, который позволяет указать фабрику хэшеров паролей для каждого типа пользователя, которая, в свою очередь, может решить, нужно ли создавать выделенные экземпляры хэшеров паролей для каждого пользователя.
Чтобы интегрировать наш объект пользователя, нам нужны две точки интеграции:
PasswordFieldHasher, который имеет доступ к экземпляру пользователя и делегирует расчет и проверку хеша определению поля пароля. Хэшер паролей должен быть настроен с указанием имени поля, с которым он должен работать (в нашем случаеpassword).UserAwarePasswordHasherFactory, который создает выделенный экземплярPasswordFieldHasherдля каждого объекта пользователя.
Чтобы достичь этого, мы определяем сервис фабрики, который создает экземпляры PasswordFieldHasher, как указано выше:
# Фабрика по обработке паролей отвечает за проверку хэша пароля для данного пользователя. Поскольку нам требуется специальная обработка
# обработка для работы с полем пароля, мы используем UserAwarePasswordHasherFactory для создания выделенного
# хэшера для каждого пользователя. Этот сервис настроен в pimcore.security.password_hasher_factories для работы с нашей моделью пользователя.
services:
website_demo.security.password_hasher_factory:
class: Pimcore\Security\Hasher\Factory\UserAwarePasswordHasherFactory
arguments:
- Pimcore\Security\Hasher\PasswordFieldHasher
- ['password']
Теперь, вместо настройки хэшера паролей в security.password_hashers, как это делается стандартным способом Symfony, настройте
сервис фабрики хэшера паролей в pimcore.security.password_hasher_factories. Это всего лишь дополнительный способ создания хэшеров паролей - если
вам не нужна какая-либо специфическая обработка, просто придерживайтесь стандартного способа Symfony.
pimcore:
security:
# фабрика хэширования паролей, как определено в services.yaml
password_hasher_factories:
App\Model\DataObject\User: website_demo.security.password_hasher_factory
Когда хэшер паролей загружается для объекта App\Model\DataObject\User, UserAwarePasswordHasherFactory создает выделенный
экземпляр PasswordFieldHasher вместо того, чтобы всегда возвращать один и тот же экземпляр для всех пользователей.
Настройка файрволла
Теперь мы можем использовать все созданные сервисы в конфигурации файрволла. В качестве примера настроим простую аутентификацию http_basic. Наша окончательная конфигурация выглядит следующим образом:
pimcore:
security:
# фабрика хэширования паролей, как определено в services.yaml
password_hasher_factories:
App\Model\DataObject\User: website_demo.security.password_hasher_factory
security:
providers:
# провайдер пользователей, как определено в services.yaml
demo_cms_provider:
id: website_demo.security.user_provider
firewalls:
# файрволл demo_cms действителен для всего сайта
demo_cms_fw:
# провайдер, определённый выше
provider: demo_cms_provider
http_basic: ~
Это поможет вам начать работу с пользовательской системой аутентификации, основанной на объектах Pimcore. Дополнительную информацию смотрите в разделе:
- Демонстрационный вариант, который служит основой для данного руководства и реализует форму входа в систему/сеанс.
- Документация Symfony Security Component
Вы можете предложить улучшение документации или задать вопрос в комментариях.
Если вам нужна полноценная консультация — вы можете заказать её на нашем сайте.