如何使用FoS Use Bundle的自定义身份验证器

时间:2014-07-18 00:15:07

标签: security symfony authentication fosuserbundle

我已经设置了一个自定义身份验证器,用于在用户登录时对其进行身份验证,按照the Symfony2 cookbook article here,但是在用户进行身份验证后,我返回了经过身份验证的令牌,我收到了一个错误,即没有提供商可用于此...

所以我继续前进安装&根据说明配置了FoS用户包,但我现在收到错误

The service "security.authentication.manager" has a dependency on a non-existent
service "security.user.provider.concrete.fos_userbundle"`

我认为这是因为provider: fos_userbundle添加到我的simple_form:配置(使用自定义身份验证器时需要代替form_login:

虽然现在我已经使用此行再次测试了它,并在尝试登录时遇到了不同的错误...

An exception occurred while executing 'INSERT INTO FosUser (username, 
username_canonical, email, email_canonical, enabled, salt, password, last_login, 
locked, expired, expires_at, confirmation_token, password_requested_at, roles,
credentials_expired, credentials_expire_at, client_id) VALUES (?, ?, ?, ?, ?, ?,
?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)' with params ["disco-user1", "disco-user1",
null, null, 0, "m6fnve0kuxw0cwggscgwc4wwogsk08o", "Dnuo1BKSAUM+690XOQYX8lfZq3I=",
"2014-07-18 01:10:33", 0, 0, null, null, null, "a:1:{i:0;s:11:\"ROLE_CLIENT\";}",
0, null, 55]:

SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'email' cannot be
null

但是我不知道它来自哪里,因为列必须在Bundle配置中的某处配置,对吧?

这是我的security.yml文件内容

security:
#    providers:
#        in_memory:
#            memory:
#                users:
#                    ryan:  { password: ryanpass, roles: 'ROLE_USER' }
#                    admin: { password: kittens, roles: 'ROLE_ADMIN' }

    role_hierarchy:
        ROLE_MANAGE_OWN_APPS:
            - ROLE_ADD_OWN_APP
            - ROLE_VIEW_OWN_APP
            - ROLE_EDIT_OWN_APP
            - ROLE_DELETE_OWN_APP
        ROLE_MANAGE_OWN_GALLERIES:
            - ROLE_ADD_OWN_GALLERY
            - ROLE_VIEW_OWN_GALLERY
            - ROLE_EDIT_OWN_GALLERY
            - ROLE_DELETE_OWN_GALLERY
        ROLE_MANAGE_OWN_DATA:
            - ROLE_MANAGE_OWN_DETAILS
            - ROLE_VIEW_OWN_CLIENT
            - ROLE_MANAGE_OWN_APPS
            - ROLE_MANAGE_OWN_GALLERIES
        ROLE_MANAGE_APPS:
            - ROLE_ADD_APP
            - ROLE_VIEW_ANY_APP
            - ROLE_EDIT_ANY_APP
            - ROLE_DELETE_ANY_APP
        ROLE_MANAGE_GALLERIES:
            - ROLE_ADD_GALLERY
            - ROLE_VIEW_ANY_GALLERY
            - ROLE_EDIT_ANY_GALLERY
            - ROLE_DELETE_ANY_GALLERY
        ROLE_MANAGE_CLIENTS:
            - ROLE_VIEW_ALL_CLIENTS
            - ROLE_ADD_CLIENT
            - ROLE_VIEW_ANY_CLIENT
            - ROLE_EDIT_ANY_CLIENT
            - ROLE_DELETE_ANY_CLIENT
        ROLE_USER:
            - ROLE_MANAGE_OWN_DATA
        ROLE_ADMIN:
            - ROLE_USER
            - ROLE_MANAGE_CLIENTS
            - ROLE_MANAGE_APPS
            - ROLE_MANAGE_GALLERIES

    providers:
        fos_userbundle:
            id: fos_user.user_provider.username

    firewalls:
        dev:
            pattern: ^/(_(profiler|wdt)|css|images|js)/
            security: false

        secured_area:
            pattern: ^/
            anonymous: ~
            simple_form:
                authenticator: flexion.security.authenticator
                login_path: login
                check_path: login_check
                provider: fos_userbundle
                csrf_provider: form.csrf_provider
                default_target_path:  login_redirect
#            remember_me:
#                key:      "%secret%"
#                lifetime: 31536000 # 365 days in seconds
#                path:     /
#                domain:   ~ # Defaults to the current domain from $_SERVER
            logout:
                path:   logout
                target: login

    access_control:
        - { path: ^/admin/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: ^/admin/clients, roles: ROLE_VIEW_ALL_CLIENTS }
        - { path: ^/admin/client/me, roles: ROLE_VIEW_OWN_CLIENT }
        - { path: ^/admin/client/\d+$, roles: [ROLE_VIEW_OWN_CLIENT, ROLE_VIEW_ALL_CLIENTS] }
        - { path: ^/admin/client/add$, roles: [ROLE_ADD_CLIENT] }
        - { path: ^/admin/client/\d+/edit$, roles: [ROLE_EDIT_OWN_CLIENT, ROLE_EDIT_ANY_CLIENT] }
        - { path: ^/admin/client/\d+/delete, roles: [ROLE_DELETE_OWN_CLIENT, ROLE_DELETE_ANY_CLIENT] }
        - { path: ^/admin/apps, roles: [ROLE_VIEW_ANY_APP] }
        - { path: ^/admin/app/\d+$, roles: [ROLE_VIEW_OWN_APP, ROLE_VIEW_ANY_APP] }
        - { path: ^/admin/app/add$, roles: [ROLE_ADD_OWN_APP, ROLE_ADD_ANY_APP] }
        - { path: ^/admin/app/\d+/edit$, roles: [ROLE_EDIT_OWN_APP, ROLE_EDIT_ANY_APP] }
        - { path: ^/admin/app/\d+/delete, roles: [ROLE_DELETE_OWN_APP, ROLE_DELETE_ANY_APP] }
        - { path: ^/admin/galleries, roles: [ROLE_VIEW_ANY_GALLERY] }
        - { path: ^/admin/gallery/\d+$, roles: [ROLE_VIEW_OWN_GALLERY, ROLE_VIEW_ANY_GALLERY] }
        - { path: ^/admin/gallery/add$, roles: [ROLE_ADD_ANY_GALLERY] }
        - { path: ^/admin/gallery/\d+/edit$, roles: [ROLE_EDIT_OWN_GALLERY, ROLE_EDIT_ANY_GALLERY] }
        - { path: ^/admin/gallery/\d+/delete, roles: [ROLE_DELETE_OWN_GALLERY, ROLE_DELETE_ANY_GALLERY] }

    encoders:
        Symfony\Component\Security\Core\User\User: plaintext

来自config.yml的fos相关位......

fos_user:
    db_driver: orm # other valid values are 'mongodb', 'couchdb' and 'propel'
    firewall_name: secured_area
    user_class: Flexion\DiscoveryComponentAdminBundle\Entity\User

如果它有帮助......我的自定义验证器......

    <?php
    /**
     * Created by PhpStorm.
     * User: toby
     * Date: 17/07/2014
     * Time: 22:20
     */

    namespace Flexion\DiscoveryComponentAdminBundle\Security;


    use Doctrine\ORM\EntityManager;
    use Flexion\DiscoveryComponentAdminBundle\Entity\User;
    use Flexion\DiscoveryComponentBundle\Entity\Client;
    use Flexion\DiscoveryComponentBundle\Entity\ClientRepository;
    use GuzzleHttp\Client as GuzzleClient;
    use GuzzleHttp\Message\ResponseInterface;
    use Symfony\Component\HttpFoundation\Request;
    use Symfony\Component\Security\Core\Authentication\SimpleFormAuthenticatorInterface;
    use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
    use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
    use Symfony\Component\Security\Core\Exception\AuthenticationException;
    use Symfony\Component\Security\Core\User\UserProviderInterface;

    class FlexionAuthenticator implements SimpleFormAuthenticatorInterface
    {
        /**
         * @var array
         */
        protected $rolesMap;

        /**
         * @var ClientRepository
         */
        protected $clientRepository;

        /**
         * @var EntityManager
         */
        private $entityManager;

        /**
         * @param array            $rolesMap
         * @param ClientRepository $clientRepository
         * @param EntityManager    $entityManager
         */
        public function __construct( $rolesMap, ClientRepository $clientRepository, EntityManager $entityManager )
        {
            $this->rolesMap         = $rolesMap;
            $this->clientRepository = $clientRepository;
            $this->entityManager    = $entityManager;
        }


        /**
         * @param TokenInterface        $token
         * @param UserProviderInterface $userProvider
         * @param                       $providerKey
         *
         * @return UsernamePasswordToken
         */
        public function authenticateToken( TokenInterface $token, UserProviderInterface $userProvider, $providerKey )
        {
            $username = $token->getUsername();
            $password = $token->getCredentials();
            $user     = new User;
            $user->setUsername( $username )
                 ->setPassword( $password );

            $uri = 'http://some-domain.com/auth' .
                   '?userId=' . urlencode( $user->getUsername() ) .
                   "&passwordHash=" . urlencode( $user->getPassword() );

            /** @var GuzzleClient $guzzleClient */
            $guzzleClient = new GuzzleClient();
            /** @var ResponseInterface $response */
            /** @noinspection PhpVoidFunctionResultUsedInspection */
            $response = $guzzleClient->get( $uri );

            if (200 != $response->getStatusCode()) {
                throw new AuthenticationException(
                    'There was a problem connecting to the authentication service.  Please try again.'
                );
            }

            $responseJson = @$response->json();

            if (empty( $responseJson['status'] )) {
                throw new AuthenticationException(
                    'There was a problem connecting to the authentication service.  Please try again.'
                );
            }

            if ('OK' !== $responseJson['status']) {
                $msg = ! empty( $responseJson['message'] ) ? $responseJson['message'] : 'Incorrect credentials';
                throw new AuthenticationException( $msg );
            }

            if (empty( $responseJson['roles'] )) {
                throw new AuthenticationException( 'Authenticated, but with no role.  Please try again.' );
            }

            $returnedRoles = $responseJson['roles'];
            if ( ! is_array( $returnedRoles )) {
                $returnedRoles = [ $returnedRoles ];
            }

            $roles = [ ];
            foreach ($returnedRoles as $role) {
                if ( ! empty( $this->rolesMap[$role] )) {
                    $roles[] = $this->rolesMap[$role];
                }
            }

            if (empty( $roles )) {
                throw new AuthenticationException( 'Authenticated, but with no role.  Please try again.' );
            }

            /** @noinspection PhpUndefinedMethodInspection */
            $client = @$this->clientRepository->findOneByUsername( $username );

            if (empty( $client )) {
                $client = new Client;
                $client->setUsername( $username )
                       ->setName( $username );
                $this->entityManager->persist( $client );
                $this->entityManager->flush();
            }

            $user->setClient( $client );
            $user->setRoles( $roles );

            return new UsernamePasswordToken(
                $user, $user->getPassword(),
                $providerKey,
                $user->getRoles()
            );
        }

        /**
         * Indicates if this class can authenticate a given token
         *
         * @param TokenInterface $token
         * @param                $providerKey
         *
         * @return bool
         */
        public function supportsToken( TokenInterface $token, $providerKey )
        {
            return $token instanceof FlexionUsernamePasswordToken;
        }

        /**
         * Creates the user token with user's login credentials
         *
         * @param Request $request
         * @param string  $username
         * @param string  $password
         * @param         $providerKey
         *
         * @return UsernamePasswordToken
         */
        public function createToken( Request $request, $username, $password, $providerKey )
        {
            return new FlexionUsernamePasswordToken( $username, $password, $providerKey );
        }
    }

0 个答案:

没有答案