Symfony 4 Guard Neo4j OGM - PullRequest
       74

Symfony 4 Guard Neo4j OGM

0 голосов
/ 06 мая 2018

У меня возникли проблемы с получением пакета Neo4j OGM / Symfony для работы с Symfony Guard. Я успешно добавил пользователей в базу данных. к сожалению, он не хочет входить в систему, и я получаю следующую ошибку:

Symfony\Component\Security\Core\Exception\AuthenticationServiceException: Class "App\Entity\Generic\User" is not a valid entity or mapped super class. in /home/vagrant/Code/support4neo/vendor/symfony/security/Core/Authentication/Provider/DaoAuthenticationProvider.php:85 Stack trace: 
#0 /home/vagrant/Code/support4neo/vendor/symfony/http-foundation/Session/Storage/NativeSessionStorage.php(142): session_start() 
#1 /home/vagrant/Code/support4neo/vendor/symfony/http-foundation/Session/Storage/NativeSessionStorage.php(299): Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage->start() 
#2 /home/vagrant/Code/support4neo/vendor/symfony/http-foundation/Session/Session.php(249): Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage->getBag('attributes') 
#3 /home/vagrant/Code/support4neo/vendor/symfony/http-foundation/Session/Session.php(271): Symfony\Component\HttpFoundation\Session\Session->getBag('attributes') 
#4 /home/vagrant/Code/support4neo/vendor/symfony/http-foundation/Session/Session.php(73): Symfony\Component\HttpFoundation\Session\Session->getAttributeBag() 
#5 /home/vagrant/Code/support4neo/vendor/symfony/security/Http/Firewall/ContextListener.php(88): Symfony\Component\HttpFoundation\Session\Session->get('_security_main') 
#6 /home/vagrant/Code/support4neo/vendor/symfony/security-bundle/Debug/WrappedListener.php(46): Symfony\Component\Security\Http\Firewall\ContextListener->handle(Object(Symfony\Component\HttpKernel\Event\GetResponseEvent)) 
#7 /home/vagrant/Code/support4neo/vendor/symfony/security-bundle/Debug/TraceableFirewallListener.php(35): Symfony\Bundle\SecurityBundle\Debug\WrappedListener->handle(Object(Symfony\Component\HttpKernel\Event\GetResponseEvent)) 
#8 /home/vagrant/Code/support4neo/vendor/symfony/security/Http/Firewall.php(56): Symfony\Bundle\SecurityBundle\Debug\TraceableFirewallListener->handleRequest(Object(Symfony\Component\HttpKernel\Event\GetResponseEvent), Object(Symfony\Component\DependencyInjection\Argument\RewindableGenerator)) 
#9 /home/vagrant/Code/support4neo/vendor/symfony/security-bundle/EventListener/FirewallListener.php(48): Symfony\Component\Security\Http\Firewall->onKernelRequest(Object(Symfony\Component\HttpKernel\Event\GetResponseEvent)) 
#10 [internal function]: Symfony\Bundle\SecurityBundle\EventListener\FirewallListener->onKernelRequest(Object(Symfony\Component\HttpKernel\Event\GetResponseEvent), 'kernel.request', Object(Symfony\Component\HttpKernel\Debug\TraceableEventDispatcher)) 
#11 /home/vagrant/Code/support4neo/vendor/symfony/event-dispatcher/Debug/WrappedListener.php(104): call_user_func(Array, Object(Symfony\Component\HttpKernel\Event\GetResponseEvent), 'kernel.request', Object(Symfony\Component\HttpKernel\Debug\TraceableEventDispatcher)) 
#12 /home/vagrant/Code/support4neo/vendor/symfony/event-dispatcher/EventDispatcher.php(212): Symfony\Component\EventDispatcher\Debug\WrappedListener->__invoke(Object(Symfony\Component\HttpKernel\Event\GetResponseEvent), 'kernel.request', Object(Symfony\Component\EventDispatcher\EventDispatcher)) 
#13 /home/vagrant/Code/support4neo/vendor/symfony/event-dispatcher/EventDispatcher.php(44): Symfony\Component\EventDispatcher\EventDispatcher->doDispatch(Array, 'kernel.request', Object(Symfony\Component\HttpKernel\Event\GetResponseEvent)) 
#14 /home/vagrant/Code/support4neo/vendor/symfony/event-dispatcher/Debug/TraceableEventDispatcher.php(139): Symfony\Component\EventDispatcher\EventDispatcher->dispatch('kernel.request', Object(Symfony\Component\HttpKernel\Event\GetResponseEvent)) 
#15 /home/vagrant/Code/support4neo/vendor/symfony/http-kernel/HttpKernel.php(125): Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcher->dispatch('kernel.request', Object(Symfony\Component\HttpKernel\Event\GetResponseEvent)) 
#16 /home/vagrant/Code/support4neo/vendor/symfony/http-kernel/HttpKernel.php(66): Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object(Symfony\Component\HttpFoundation\Request), 1) 
#17 /home/vagrant/Code/support4neo/vendor/symfony/http-kernel/Kernel.php(190): Symfony\Component\HttpKernel\HttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true) 
#18 /home/vagrant/Code/support4neo/public/index.php(37): Symfony\Component\HttpKernel\Kernel->handle(Object(Symfony\Component\HttpFoundation\Request)) 
#19 {main}

Что я могу делать не так?

Заранее спасибо!

Класс пользователя:

<?php
/**
 * Created by PhpStorm.
 * User: kevin.oosterhout
 * Date: 24/04/2018
 * Time: 20:58
 */

namespace App\Entity\Generic;

use GraphAware\Neo4j\Client\Client;
use GraphAware\Neo4j\OGM\Annotations as OGM;
use Symfony\Component\Security\Core\User\UserInterface;


/**
 *
 * @OGM\Node(label="User")
 */
class User implements UserInterface
{

    /**
     * @OGM\GraphId()
     */
    protected $id;
    /**
     * @OGM\Property(type="string")
     */
    protected $firstname;
    /**
     * @OGM\Property(type="string")
     */
    protected $lastname;
    /**
     * @OGM\Property(type="string")
     */
    protected $email;
    /**
     * @OGM\Property(type="string")
     */
    protected $password;

    /**
     * @return mixed
     */
    public function getFirstname()
    {
        return $this->firstname;
    }

    /**
     * @return mixed
     */
    public function getLastname()
    {
        return $this->lastname;
    }

    /**
     * @return mixed
     */
    public function getEmail()
    {
        return $this->email;
    }

    /**
     * @return mixed
     */
    public function getPassword()
    {
        return $this->password;
    }

    /**
     * @param mixed $firstname
     */
    public function setFirstname($firstname): void
    {
        $this->firstname = $firstname;
    }

    /**
     * @param mixed $lastname
     */
    public function setLastname($lastname): void
    {
        $this->lastname = $lastname;
    }

    /**
     * @param mixed $email
     */
    public function setEmail($email): void
    {
        $this->email = $email;
    }

    /**
     * @param mixed $password
     */
    public function setPassword($password): void
    {
        $this->password = $password;
    }


    /**
     * Returns the roles granted to the user.
     *
     * <code>
     * public function getRoles()
     * {
     *     return array('ROLE_USER');
     * }
     * </code>
     *
     * Alternatively, the roles might be stored on a ``roles`` property,
     * and populated in any number of different ways when the user object
     * is created.
     *
     * @return (Role|string)[] The user roles
     */
    public function getRoles()
    {
        return array('ROLE_USER');
    }

    /**
     * Returns the salt that was originally used to encode the password.
     *
     * This can return null if the password was not encoded using a salt.
     *
     * @return string|null The salt
     */
    public function getSalt()
    {
        return null;
    }

    /**
     * Returns the username used to authenticate the user.
     *
     * @return string The username
     */
    public function getUsername()
    {
        return $this->email;
    }

    /**
     * Removes sensitive data from the user.
     *
     * This is important if, at any given point, sensitive information like
     * the plain-text password is stored on this object.
     */
    public function eraseCredentials()
    {
        // TODO: Implement eraseCredentials() method.
    }
}

Класс аутентификатора:

<?php
/**
 * Created by PhpStorm.
 * User: kevin.oosterhout
 * Date: 03/05/2018
 * Time: 17:37
 */

namespace App\Security;


use App\Entity\Generic\User;
use App\Forms\LoginForm;
use GraphAware\Neo4j\OGM\EntityManager;
use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Guard\Authenticator\AbstractFormLoginAuthenticator;

class LoginFormAuthenticator extends AbstractFormLoginAuthenticator
{

    public function getCredentials(Request $request)
    {
        return array(
            'username' => $request->request->get('_username'),
            'password' => $request->request->get('_password'),
        );
    }

    public function getUser($credentials, UserProviderInterface $userProvider)
    {
        if($credentials['username'] === null){
            return null;
        }
        $user = $userProvider->loadUserByUsername($credentials['username']);

        return $user;

    }

    public function checkCredentials($credentials, UserInterface $user)
    {

        return true;
    }

    protected function getLoginUrl()
    {
        // TODO: Implement getLoginUrl() method.
    }

    public function supports(Request $request)
    {
        return false;
    }

    public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey)
    {
        // TODO: Implement onAuthenticationSuccess() method.
    }
}

Security.Yaml

security:
    encoders:
        App\Entity\Generic\User:
          algorithm: bcrypt

    # https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers
    providers:
        UserProvider:
            id: 'App\Security\UserProvider'

    firewalls:
        dev:
            pattern: ^/(_(profiler|wdt)|css|images|js)/
            security: false
        main:
            anonymous: ~
            form_login:
                login_path: login
                check_path: login
            guard:
                authenticators:
                    - 'App\Security\LoginFormAuthenticator'



            # activate different ways to authenticate

            # http_basic: true
            # https://symfony.com/doc/current/security.html#a-configuring-how-your-users-will-authenticate

            # form_login: true
            # https://symfony.com/doc/current/security/form_login_setup.html

    # Easy way to control access for large sections of your site
    # Note: Only the *first* access control that matches will be used
    access_control:
        # - { path: ^/admin, roles: ROLE_ADMIN }
        # - { path: ^/profile, roles: ROLE_USER }

Пользовательский провайдер:

<?php
/**
 * Created by PhpStorm.
 * User: kevin.oosterhout
 * Date: 04/05/2018
 * Time: 07:38
 */

namespace App\Security;


use App\Entity\Generic\User;
use GraphAware\Neo4j\OGM\EntityManager;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;

class UserProvider implements UserProviderInterface
{

    protected $userRepository;

    public function __construct(EntityManager $entityManager)
    {
        $this->userRepository = $entityManager->getRepository(User::class);
    }

    /**
     * @param string $username
     * @return null|User
     */
    public function loadUserByUsername($username)
    {

        return $this->userRepository->findOneBy(['email' => $username]);
    }

    public function refreshUser(UserInterface $user)
    {

        if (!$user instanceof User) {
            throw new UnsupportedUserException(
                sprintf('Instance of %s is not support', get_class($user))
            );
        }

        return $this->loadUserByUsername($user->getUsername());
    }

    public function supportsClass($class)
    {
        return User::class === $class;
    }
}

Edit: В настоящее время он не регистрирует меня и не выдает ошибку. Я выполнил шаги, объясненные @dbrumann и @Christophe Willemsen

Ответы [ 2 ]

0 голосов
/ 06 мая 2018

Ответ от @dbrumman правильный, вам понадобится пользовательский UserProvider.

У меня есть демонстрационный пример на Github, проверьте здесь: https://github.com/ikwattro/neo4j-ogm-symfony-security

Существует также PullRequest, в котором показано, как добавлять роли на основе содержимого Neo4j:

https://github.com/ikwattro/neo4j-ogm-symfony-security/pull/1/files

0 голосов
/ 06 мая 2018

Я думаю, что проблема может быть с вашим security.yaml:

providers:
    UserProvider:
        entity:
            class: 'App\Entity\Generic\User'
            property: email

Этот провайдер пытается использовать Doctrine ORM для загрузки пользователей из. Поскольку ваш User-entity не является Doctrine-Entity, то есть пропускает аннотации доктрины, он терпит неудачу. Несмотря на то, что пакет регистрирует менеджеры сущностей, они, похоже, не используются провайдером пользователей.

Вы можете создать пользовательского провайдера , который вдохновлен EntityUserProvider .

Я не уверен, что менеджеры сущностей ogm придерживаются интерфейсов доктрины, но если они это сделают, вы сможете сконфигурировать поставщика пользователей доктрины по умолчанию для использования менеджера сущностей neo4j, настроив конфигурацию сервиса, но это реальная проблема потому что вам нужно переписать UserProvider-сервис, а затем внедрить новый ManagerRegistry с вашим менеджером сущностей в нем. Таким образом, написание пользовательского UserProvider действительно является предпочтительным способом.

...