0

我在让 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.
    }
}

安全.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;
    }
}

编辑:目前它没有让我登录,也没有给我一个错误。我已按照@dbrumann 和@Christophe Willemsen 解释的步骤进行操作

4

2 回答 2

2

我认为问题可能出在您的security.yaml

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

这个提供者尝试使用 Doctrine ORM 来加载用户。由于您的用户实体不是教义实体,即缺少教义注释,因此它失败了。即使捆绑包注册了实体管理器,用户提供者似乎也没有使用它们。

您可以创建一个受EntityUserProvider启发的自定义用户提供程序

我不确定 ogm 实体管理器是否遵守教义的接口,但如果他们这样做,您也许可以通过调整服务配置来配置默认的教义用户提供程序以使用 neo4j 实体管理器,但这真的很痛苦,因为您有覆盖 UserProvider-service,然后注入一个新的 ManagerRegistry,其中包含您的实体管理器。因此,编写自定义 UserProvider 似乎确实是首选方式。

于 2018-05-06T07:52:15.270 回答
1

@dbrumman 的答案是正确的,您将需要一个自定义 UserProvider。

我在 Github 上有一个演示示例,请在此处查看:https ://github.com/ikwattro/neo4j-ogm-symfony-security

还有一个 PullRequest 展示了如何根据 Neo4j 内容添加角色:

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

于 2018-05-06T10:02:30.410 回答