Symfony3:抛出新的异常终止会话

时间:2017-06-13 08:02:59

标签: symfony session exception

我有一个奇怪的行为:当抛出异常而我的用户断开连接时。

我使用SF3和用户提供商(基本SF身份验证)。 我抛出了异常,因此我被重定向到自定义错误页面。 这个问题发生在dev和prod environnement上。

我没有找到任何关于此的文档,你知道它为什么会发生以及如何解决这个问题吗?

这是我的代码:

表单身份验证器:

    <?php

namespace AppBundle\Security;

use AppBundle\Security\User\UserProvider;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
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\Exception\CustomUserMessageAuthenticationException;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Guard\AbstractGuardAuthenticator;

/**
 * Class FormAuthenticator
 * @package AppBundle\Security\User
 */
class FormAuthenticator extends AbstractGuardAuthenticator
{

    /**
     * @var \Symfony\Component\Routing\RouterInterface
     */
    private $router;

    /**
     * Default message for authentication failure.
     *
     * @var string
     */
    private $failMessage = 'Invalid credentials';

    /**
     * Creates a new instance of FormAuthenticator
     * FormAuthenticator constructor.
     * @param RouterInterface $router
     */
    public function __construct(RouterInterface $router)
    {
        $this->router = $router;
    }

    /**
     * {@inheritdoc}
     */
    public function getCredentials(Request $request)
    {
        if ($request->getPathInfo() == '/login' && $request->isMethod('POST')) {
            return [
                'username' => $request->request->get('username'),
                'password' => $request->request->get('password'),
            ];
        }
        return null;
    }

    /**
     * {@inheritdoc}
     */
    public function getUser($credentials, UserProviderInterface $userProvider)
    {
        if (!$userProvider instanceof UserProvider) {
            return null;
        }

        try {
            return $userProvider->loadUserByUsername($credentials['username']);
        } catch (UsernameNotFoundException $e) {
            throw new CustomUserMessageAuthenticationException($this->failMessage);
        }
    }

    /**
     * {@inheritdoc}
     */
    public function checkCredentials($credentials, UserInterface $user)
    {
        $passwordEncoder = new PasswordEncoderService();
        $password = $passwordEncoder->encodePassword($user->getUsername(), $user->getEmail(), $credentials['password'], $user->getSalt());
        if ($user->getPassword() === $password['encodedPassword']) {
            return true;
        }
        throw new CustomUserMessageAuthenticationException($this->failMessage);
    }

    /**
     * {@inheritdoc}
     */
    public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey)
    {
        $url = $this->router->generate('home');
        return new RedirectResponse($url);
    }

    /**
     * {@inheritdoc}
     */
    public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
    {
        $request->getSession()->set(Security::AUTHENTICATION_ERROR, $exception);
        $url = $this->router->generate('login');
        return new RedirectResponse($url);
    }

    /**
     * {@inheritdoc}
     */
    public function start(Request $request, AuthenticationException $authException = null)
    {
        $url = $this->router->generate('login');
        return new RedirectResponse($url);
    }

    /**
     * {@inheritdoc}
     */
    public function supportsRememberMe()
    {
        return true;
    }
}

用户提供商:

   <?php

namespace AppBundle\Security\User;

use AppBundle\Services\MawsHelper;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;

/**
 * Class UserProvider
 * @package AppBundle\Security
 */
class UserProvider implements UserProviderInterface
{
    /** @var MawsHelper $mawsHelper */
    private $mawsHelper;

    /**
     * UserProvider constructor.
     * @param MawsHelper $mawsHelper
     */
    public function __construct(MawsHelper $mawsHelper)
    {
        $this->mawsHelper = $mawsHelper;
    }

    /**
     * @param string $idUser
     * @return User
     */
    public function loadUserByUsername($idUser)
    {
        // make a call to your webservice here
        $userData = $this->mawsHelper->getUserData($idUser);
        // pretend it returns an array on success, false if there is no user

        if ($userData) {
            return new User($userData['id'], $userData['firstName'], $userData['lastName'], $userData['email'], $userData['login'], $userData['password'], $userData['salt'], $userData['active'], $userData['birthDate'], $userData['datePassword'], $userData['groups'], $userData['permissions'], $userData['preferences']);
        }

        throw new UsernameNotFoundException(
            sprintf('Username "%s" does not exist.', $idUser)
        );
    }

    /**
     * @param UserInterface $user
     * @return User
     */
    public function refreshUser(UserInterface $user)
    {
        if (!$user instanceof User) {
            throw new UnsupportedUserException(
                sprintf('Instances of "%s" are not supported.', get_class($user))
            );
        }

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

    /**
     * @param string $class
     * @return bool
     */
    public function supportsClass($class)
    {
        return User::class === $class;
    }
}

Security.yml;

security:

# http://symfony.com/doc/current/security.html#b-configuring-how-users-are-loaded
providers:
    maws:
        id: app.maws_user_provider

firewalls:
    # disables authentication for assets and the profiler, adapt it according to your needs
    dev:
        pattern: ^/(_(profiler|wdt)|css|images|js)/
        security: false

    secured_area:
        anonymous: ~
        logout:
            path:   /logout
            target: /
        guard:
            authenticators:
                - form_authenticator
access_control:
    - { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
    - { path: ^/administration/*, roles: ROLE_ADMINISTRATION }
    - { path: ^/, roles: ROLE_ADMIN }

Service.yml:

# Learn more about services, parameters and containers at
# http://symfony.com/doc/current/service_container.html
parameters:
    #parameter_name: value

services:
    #service_name:
    #    class: AppBundle\Directory\ClassName
    #    arguments: ['@another_service_name', 'plain_value', '%parameter_name%']
    maws.exchange:
        class: AppBundle\Services\RequestService
        arguments: ['%dispatcher_host%']
    maws.helper:
        class: AppBundle\Services\MawsHelper
        arguments: ['@maws.exchange']
    session.service:
        class: AppBundle\Services\SessionService
    populate.session.service:
        class: AppBundle\Services\PopulateSessionService
        arguments: ['@maws.exchange']
    app.local.action_listener:
        class: AppBundle\EventListener\LocaleListener
        arguments: ['en']
        tags:
                    - { name: kernel.event_subscriber ,  priority: -257}
    app.is_unique_validator:
        class: AppBundle\Forms\Constraint\IsUniqueValidator
        arguments: ['@maws.exchange']
        tags:
            - { name: validator.constraint_validator }
    app.twig_extension:
        class: AppBundle\Twig\AppExtension
        public: true
        tags:
            - { name: twig.extension }
    app.maws_user_provider:
        class: AppBundle\Security\User\UserProvider
        arguments: ['@maws.helper']
    form_authenticator:
        class: AppBundle\Security\FormAuthenticator
        arguments: ["@router"]
    app.user_locale_listener:
            class: AppBundle\EventListener\UserLocaleListener
            arguments: ['@session']
            tags:
                - { name: kernel.event_listener, event: security.interactive_login, method: onInteractiveLogin }

0 个答案:

没有答案