Symfony无限登录循环

时间:2015-12-15 19:33:55

标签: php symfony loops authentication login

我一直试图解决这个问题我已经使用我的Symfony App了 当我尝试登录时,我会被重定向到我的仪表板路径,因为它应该这样做但是出于某种原因,在加载仪表板页面之前,它似乎点击我的登录验证器试图重新验证我的用户凭据但是这次有没有要验证的凭据,因为eraseCredentials()方法从authToken中删除了我的密码,因为第二次失败也是这个程序继续运行在一个循环中击中验证器并且反复失败并且我唯一的方式能够通过注销来阻止此行为。

这是我的登录验证器

   <?php
namespace Cms\UserManagerBundle\Security;

use Symfony\Component\DependencyInjection\ContainerInterface;
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\Encoder\EncoderFactoryInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Doctrine\ORM\EntityManager;

class LoginAuthenticator implements SimpleFormAuthenticatorInterface
{
    private $encoderFactory;

    public function __construct(EncoderFactoryInterface $encoderFactory, EntityManager $entityManager, ContainerInterface $container)
    {
        $this->encoderFactory = $encoderFactory;
        $this->em = $entityManager;
        $this->container = $container;
    }

    public function authenticateToken(TokenInterface $token, UserProviderInterface $userProvider, $providerKey)
    {

        try {
            $user = $userProvider->loadUserByUsername($token->getUsername());
        } catch (UsernameNotFoundException $e) {
            throw new AuthenticationException('Invalid username or password');
        }


        $encoder = $this->encoderFactory->getEncoder($user);
        $passwordValid = $encoder->isPasswordValid(
            $user->getPassword(),
            $token->getCredentials(),
            $user->getSalt()
        );

        //$session = $this->container->get('session');
       // $passwordValid = true;
        //get default language
        //$session->language('language/id');

        if ($passwordValid) {



            $now = new \DateTime();
            $user->setLastlogin($now);
            $user->setLoggedInn($user->getLoggedInn()+1);
            $this->em->flush();
            $roles = $user->getRoles();

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


        }else{

            throw new AuthenticationException('Invalid username or password');

        }


    }

    public function supportsToken(TokenInterface $token, $providerKey)
    {
        return $token instanceof UsernamePasswordToken
            && $token->getProviderKey() === $providerKey;
    }

    public function createToken(Request $request, $username, $password, $providerKey)
    {
        return new UsernamePasswordToken($username, $password, $providerKey);
    }
}

这是我的防火墙设置

security:
    encoders:
        Cms\UserManagerBundle\Entity\User: sha512

    role_hierarchy:
        ROLE_ADMIN:       ROLE_USER
        ROLE_SUPER_ADMIN: ROLE_ADMIN

#    providers:
#        fos_userbundle:
#            id: fos_user.user_provider.username
    providers:
        cms_users:
            id: cms_user_provider
        our_db_provider:
            entity:
                class: UserManagerBundle:User
                property: username

    firewalls:
        cms:
            pattern: ^/admin/
            simple_form:
                authenticator: login_authenticator
                provider: cms_users
                csrf_provider: form.csrf_provider
                login_path: /admin/login
                check_path: /admin/login_check
                always_use_default_target_path: true
                default_target_path: /admin/dashboard
            logout:
                path:   /admin/logout
                target: /admin/login
            anonymous:    true
#        default:
#            pattern:    ^/
#            http_basic: ~

    access_control:
        - { path: ^/admin/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: ^/admin/*, role: ROLE_ADMIN }
        - { path: ^/*, role: IS_AUTHENTICATED_ANONYMOUSLY }

我的登录控制器

<?php

namespace Cms\UserManagerBundle\Controller;

use Cms\CoreBundle\Controller\CoreController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoder;


class SecurityController extends CoreController
{

    public function loginAction(Request $request)
    {

        /** @var $session \Symfony\Component\HttpFoundation\Session\Session */
        $session = $request->getSession();

        if (class_exists('\Symfony\Component\Security\Core\Security')) {
            $authErrorKey = Security::AUTHENTICATION_ERROR;
            $lastUsernameKey = Security::LAST_USERNAME;
        }

        // get the error if any (works with forward and redirect -- see below)
        if ($request->attributes->has($authErrorKey)) {
            $error = $request->attributes->get($authErrorKey);
        } elseif (null !== $session && $session->has($authErrorKey)) {
            $error = $session->get($authErrorKey);
            $error = $error->getMessage();
            $session->remove($authErrorKey);
        } else {
            $error = null;
        }

        // last username entered by the user
        $lastUsername = (null === $session) ? '' : $session->get($lastUsernameKey);

        if ($this->has('security.csrf.token_manager')) {
            $csrfToken = $this->get('security.csrf.token_manager')->getToken('authenticate')->getValue();
        }

        return $this->renderLogin(array(
            'last_username' => $lastUsername,
            'error' => $error,
            'csrf_token' => $csrfToken,
        ));
    }



    public function generateUrl($route, $parameters = array(), $referenceType = UrlGeneratorInterface::ABSOLUTE_PATH)
    {
        return $this->container->get('router')->generate($route, $parameters, $referenceType);
    }


    /**
     * Renders the login template with the given parameters. Overwrite this function in
     * an extended controller to provide additional data for the login template.
     *
     * @param array $data
     *
     * @return \Symfony\Component\HttpFoundation\Response
     */
    protected function renderLogin(array $data)
    {
        return $this->render('UserManagerBundle:Security:login.html.twig', $data);
    }


    public function checkAction()
    {
        throw new \RuntimeException('You must configure the check path to be handled by the firewall using form_login in your security firewall configuration.');
    }

    public function logoutAction()
    {
        throw new \RuntimeException('You must activate the logout in your security firewall configuration.');
    }



}

非常感谢任何帮助

由于 彼得

2 个答案:

答案 0 :(得分:0)

检查路径还必须允许匿名,否则如果匿名用户必须首先进行身份验证,他们如何进行身份验证?

添加

    - { path: ^/admin/login_check$, role: IS_AUTHENTICATED_ANONYMOUSLY }

答案 1 :(得分:0)

您的deleteCredentials函数必须为空。

仅在使用plainPassword时使用。


如果问题仍然存在,请与我们分享实现UserInterface的User类


编辑:

我还没有看到这个主题的日期……但是我认为我的解决方案是正确的! :)


编辑BIS

 * 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.

如果您清空密码而不是未映射的plainPassword,则循环是正常的反应。