私は、従来のユーザー フォームとまったく同じように機能するカスタム プロバイダーに取り組んでいますが、ユーザーを識別するための 2 番目のパラメーター、websiteId を指定する必要があります (動的な Web サイト プレートフォームを作成しています)。
したがって、ユーザー名はもはや一意ではありませんが、ユーザー名と websiteId の組み合わせは一意です。
カスタム認証を正常に作成しました。最後の問題は、リスナーのおかげでドメインから websiteId を取得することです。これは機能しますが、残念ながら、ドメインから Web サイト ID を取得するメソッドは認証プロバイダーの後にロードされるため、時間内にwebsiteIdを取得できません:(
リスナーの優先順位を変更しようとしました (テスト 9999、1024、255、および 0、および負の数 -9999、-1024、-255 など...)、無駄に、常に後で読み込まれます。
ここに私のコード:
services.yml:
services:
# Listeners _________________
website_listener:
class: Sybio\Bundle\WebsiteBundle\Services\Listener\WebsiteListener
arguments:
- @doctrine
- @sybio.website_manager
- @translator
- %sybio.states%
tags:
- { name: kernel.event_listener, event: kernel.request, method: onDomainParse, priority: 255 }
# Security _________________
sybio_website.user_provider:
class: Sybio\Bundle\WebsiteBundle\Security\Authentication\Provider\WebsiteUserProvider
arguments: [@website_listener, @doctrine.orm.entity_manager]
私のリスナーは「website_listener」で、それを sybio_website.user_provider の引数として使用していることがわかります。
ウェブサイト リスナー:
// ...
class WebsiteListener extends Controller
{
protected $doctrine;
protected $websiteManager;
protected $translator;
protected $websiteId;
/**
* @var array
*/
protected $entityStates;
public function __construct($doctrine, $websiteManager, $translator, $entityStates)
{
$this->doctrine = $doctrine;
$this->websiteManager = $websiteManager;
$this->translator = $translator;
$this->entityStates = $entityStates;
}
/**
* @param Event $event
*/
public function onDomainParse(Event $event)
{
$request = $event->getRequest();
$website = $this->websiteManager->findOne(array(
'domain' => $request->getHost(),
'state' => $this->entityStates['website']['activated'],
));
if (!$website) {
throw $this->createNotFoundException($this->translator->trans('page.not.found'));
}
$this->websiteId = $website->getId();
}
/**
* @param integer $websiteId
*/
public function getWebsiteId()
{
return $this->websiteId;
}
}
$websiteId はハイドレートされていますが、プロバイダーで表示されるように間に合いません...
ウェブサイト ユーザー プロバイダ:
<?php
namespace Sybio\Bundle\WebsiteBundle\Security\Authentication\Provider;
// ...
class WebsiteUserProvider implements UserProviderInterface
{
private $em;
private $websiteId;
private $userEntity;
public function __construct($websiteListener, EntityManager $em)
{
$this->em = $em;
$this->websiteId = $websiteListener->getWebsiteId(); // Try to get the website id from my listener, but it's method onDomainParse is not called in time
$this->userEntity = 'Sybio\Bundle\CoreBundle\Entity\User';
}
public function loadUserByUsername($username)
{
// I need the websiteId here to identify the user by its username and the website:
if ($user = $this->findUserBy(array('username' => $username, 'website' => $this->websiteId))) {
return $user;
}
throw new UsernameNotFoundException(sprintf('No record found for user %s', $username));
}
// ...
}
したがって、どんなアイデアでも感謝します;)認証構成のセットアップに多くの時間を費やしましたが、websiteIdを時間内に取得できません。残念です:(
あなたの答えをありがとう!
編集:
認証システムの他のファイルも理解する必要がありました.security.yml構成で認識されているため、ロード時にプロバイダーの位置を制御できないと思います:
ウェブサイト認証プロバイダー:
// ...
class WebsiteAuthenticationProvider extends UserAuthenticationProvider
{
private $encoderFactory;
private $userProvider;
/**
* @param \Symfony\Component\Security\Core\User\UserProviderInterface $userProvider
* @param UserCheckerInterface $userChecker
* @param $providerKey
* @param EncoderFactoryInterface $encoderFactory
* @param bool $hideUserNotFoundExceptions
*/
public function __construct(UserProviderInterface $userProvider, UserCheckerInterface $userChecker, $providerKey, EncoderFactoryInterface $encoderFactory, $hideUserNotFoundExceptions = true)
{
parent::__construct($userChecker, $providerKey, $hideUserNotFoundExceptions);
$this->encoderFactory = $encoderFactory;
$this->userProvider = $userProvider;
}
/**
* {@inheritdoc}
*/
protected function retrieveUser($username, UsernamePasswordToken $token)
{
$user = $token->getUser();
if ($user instanceof UserInterface) {
return $user;
}
try {
$user = $this->userProvider->loadUserByUsername($username);
if (!$user instanceof UserInterface) {
throw new AuthenticationServiceException('The user provider must return a UserInterface object.');
}
return $user;
} catch (UsernameNotFoundException $notFound) {
throw $notFound;
} catch (\Exception $repositoryProblem) {
throw new AuthenticationServiceException($repositoryProblem->getMessage(), $token, 0, $repositoryProblem);
}
}
// ...
}
工場:
// ...
class WebsiteFactory extends FormLoginFactory
{
public function getKey()
{
return 'website_form_login';
}
protected function getListenerId()
{
return 'security.authentication.listener.form';
}
protected function createAuthProvider(ContainerBuilder $container, $id, $config, $userProviderId)
{
$provider = 'security.authentication_provider.sybio_website.'.$id;
$container
->setDefinition($provider, new DefinitionDecorator('security.authentication_provider.sybio_website'))
->replaceArgument(0, new Reference($userProviderId))
->replaceArgument(2, $id)
;
return $provider;
}
}
SybioWebsiteBundle (依存関係):
// ...
class SybioWebsiteBundle extends Bundle
{
public function build(ContainerBuilder $container)
{
parent::build($container);
$extension = $container->getExtension('security');
$extension->addSecurityListenerFactory(new WebsiteFactory());
}
}
安全:
security:
firewalls:
main:
provider: website_provider
pattern: ^/
anonymous: ~
website_form_login:
login_path: /login.html
check_path: /login
logout:
path: /logout.html
target: /
providers:
website_provider:
id: sybio_website.user_provider