Guard身份验证和可序列化用户

时间:2016-08-08 15:48:10

标签: php symfony security authentication symfony-2.8

我被分配了在基于symfony的网站上改进身份验证系统的任务。细节并不重要,重要的是新的Guard组件(在Symfony 2.8中引入)非常适合这项任务。

我有以下问题:警卫DO设法验证用户&重定向到主页,但拒绝访问主页(抛出AuthenticationExpiredException),因此用户被重定向回登录。从用户POV,似乎登录总是失败。

即使是一个非常简单的项目,问题也会出现:

/* Not writing getters, setters and annotations here for readability */
class CustomUser implements UserInterface, \Serializable {
    private $id;
    protected $username;
    protected $salt;
    protected $password;

    public function __construct() {
        $this->salt = md5(uniqid(null, true));
    }

    public function serialize() {
        return serialize(array($this->id,));
    }

    public function unserialize($serialized) {
        list($this->id,) = unserialize($serialized);
    }
}

Guard类:

class CustomGuardAuthenticator extends AbstractGuardAuthenticator {
    private $container;
    private $router;

    public function __construct(ContainerInterface $container) {
        $this->container = $container;
        $this->router = $container->get('router');
    }

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

    public function getCredentials(Request $request) {
        if ($request->getPathInfo() != '/login_check' || !$request->isMethod('POST')) {
            return null;
        }

        return array(
            'username' => $request->request->get('_username'),
            'password' => $request->request->get('_password'),
        );
    }

    public function getUser($credentials, UserProviderInterface $userProvider) {
        $user = $userProvider->loadUserByUsername($credentials['username']); /* No problem here, user correctly fetched */
        return $user;
    }

    public function checkCredentials($credentials, UserInterface $user) {
        $encoder = $this->container->get('security.password_encoder');
        if (!$encoder->isPasswordValid($user, $credentials['password'])) { /* No problem here either */
            throw new BadCredentialsException();
        }

        return true;
    }

    public function onAuthenticationFailure(Request $request, AuthenticationException $exception) {
        $response = new RedirectResponse($this->router->generate('login'));
        return $response;
    }

    public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey) {
        /* Debugging show that we DO reach that */
        return new RedirectResponse($this->router->generate('homepage'));
    }

    public function supportsRememberMe() {
        return false;
    }
}

security.yml:

security:
    encoders:
        AppBundle\Entity\CustomUser:
            algorithm:        sha1
            encode_as_base64: false
            iterations:       1

    providers:
        main:
            entity: {class: AppBundle\Entity\CustomUser, property: username}

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

        main:
            pattern: ^/
            anonymous: true
            guard:
                authenticators:
                    - security.custom.guard

    access_control:
        - { path: ^/security/*, roles: IS_AUTHENTICATED_ANONYMOUSLY}
        - { path: ^/, roles: [ROLE_USER] }
  • 如果我的用户类没有实现Serializable,它确实有效。
  • 如果我的用户类实现EquatableInterface只检查id,它确实有效。
  • 如果我使用等效的AuthenticationProvider而不是Guard,它确实有用。

我希望避免使用这3种解决方法中的一种。但最重要的是,我想了解问题是什么,并不觉得最后两天浪费了!

任何帮助将不胜感激:)

0 个答案:

没有答案