Symfony 2.3 Bad Credentials自定义提供程序

时间:2013-10-15 11:36:18

标签: security symfony login symfony-2.3

此刻我完全迷失了,两天我试图弄清楚为什么我总是在登录表单上获得“Bad Credential”回复。

我使用了How to load Security Users from the Database教程。

有没有办法知道他在比较什么以获得“不良凭据”错误?

转储错误:

exception 'Symfony\Component\Security\Core\Exception\BadCredentialsException' with message 'Bad credentials' in D:\dev\workspace\esig_grandprojet\vendor\symfony\symfony\src\Symfony\Component\Security\Core\Authentication\Provider\UserAuthenticationProvider.php:89 Stack trace: 
#0 D:\dev\workspace\esig_grandprojet\app\cache\dev\classes.php(107): session_start() 
#1 D:\dev\workspace\esig_grandprojet\app\cache\dev\classes.php(184): Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage->start() 
#2 D:\dev\workspace\esig_grandprojet\app\cache\dev\classes.php(482): Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage->getBag('attributes') 
#3 D:\dev\workspace\esig_grandprojet\src\ESIG\BBC\ManagerCP2Bundle\Controller\SecurityController.php(45): Symfony\Component\HttpFoundation\Session\Session->get('_security.last_...') 
#4 [internal function]: ESIG\BBC\ManagerCP2Bundle\Controller\SecurityController->loginAction() 
#5 D:\dev\workspace\esig_grandprojet\app\bootstrap.php.cache(2844): call_user_func_array(Array, Array) 
#6 D:\dev\workspace\esig_grandprojet\app\bootstrap.php.cache(2818): Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object(Symfony\Component\HttpFoundation\Request), 1) 
#7 D:\dev\workspace\esig_grandprojet\app\bootstrap.php.cache(2947): Symfony\Component\HttpKernel\HttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true) 
#8 D:\dev\workspace\esig_grandprojet\app\bootstrap.php.cache(2249): Symfony\Component\HttpKernel\DependencyInjection\ContainerAwareHttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true) 
#9 D:\dev\workspace\esig_grandprojet\web\app_dev.php(28): Symfony\Component\HttpKernel\Kernel->handle(Object(Symfony\Component\HttpFoundation\Request)) 
#10 {main}

以下是我的文件:

我的security.yml:

security:
    encoders:
        ESIG\BBC\ManagerCP2Bundle\Entity\Utilisateur:
            algorithm: sha512
            encode_as_base64: true
            iterations: 5000

    providers:
        users:
            entity: { class: ESIGBBCManagerCP2Bundle:Utilisateur }

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

        login:
            pattern:  ^/login$
            security: false

        main:
            pattern:    /.*
            form_login:
                # The user is redirected here when he needs to login
                login_path: _security_login
                #if true, forward the user to the login form instead of redirecting
                use_forward: false
                # submit the login form here
                check_path: _security_check
                # by default, the login form *must* be a POST, not a GET
                post_only: true
                # login success redirecting options
                always_use_default_target_path: true
                default_target_path:            /
                target_path_parameter:          _target_path
                use_referer:                    false
                # login failure redirecting options
                failure_path:                     null
                failure_forward:                  false

                # field names for the username and password fields
                username_parameter:               _username
                password_parameter:               _password

                #csrf token options
                csrf_parameter:                   _csrf_token
                intention:                        authenticate

            logout: true
            security: true
            anonymous: true

            remember_me:
                key:       "%secret%"
                lifetime: 3600
                path:      /
                domain: ~ #Default to the current domain from $_SERVER

    access_control:
        - { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }        
        - { path: /.*, roles: IS_AUTHENTICATED_REMEMBERED }
        #- { path: ^/demo/secured/hello/admin/, roles: ROLE_ADMIN }
        #- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY, requires_channel: https }

我的用户实体:

<?php

namespace ESIG\BBC\ManagerCP2Bundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\AdvancedUserInterface;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;

/**
 * Utilisateur
 *
 * @ORM\Table(name="mcp2_utilisateur")
 * @ORM\Entity(repositoryClass="ESIG\BBC\ManagerCP2Bundle\Entity\UtilisateurRepository")
 * @ORM\InheritanceType("SINGLE_TABLE")
 * @ORM\DiscriminatorColumn(name="uti_discr", type="string")
 * @ORM\DiscriminatorMap({"utilisateur" = "Utilisateur", "pompier" = "Pompier"})
 * 
 * @UniqueEntity(fields="username", message="error.input.unique.user")
 * @UniqueEntity(fields="email", message="error.input.unique.mail")
 */

class Utilisateur implements AdvancedUserInterface, \Serializable
{
    /**
     * @var integer
     *
     * @ORM\Column(name="uti_id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name="uti_nom_utilisateur", type="string", length=50, unique=true)
     * @Assert\NotBlank(message="error.input.blank")
     */
    private $username;

    /**
     * @ORM\Column(name="uti_salt", type="string", length=255)
     */
    private $salt;

    /**
     * @var string
     *
     * @ORM\Column(name="uti_mot_de_passe", type="string", length=255)
     * @Assert\NotBlank(message="error.input.blank")
     */
    private $password;

    /**
     * @var string
     *
     * @ORM\Column(name="uti_email", type="string", length=100, unique=true)
     * @Assert\NotBlank(message="error.input.blank")
     * @Assert\Email(message="error.input.invalid.mail")
     */
    private $email;

    /**
     * @var boolean
     *
     * @ORM\Column(name="uti_is_active", type="boolean")
     * @Assert\NotBlank(message="error.input.blank")
     */
    private $isActive;    

    /**
     * @var boolean
     *
     * @ORM\Column(name="uti_mot_de_passe_expire", type="boolean")
     * @Assert\NotBlank(message="error.input.blank")
     */
    private $motDePasseExpire;


    /**
     * @var string
     *
     * @ORM\Column(name="uti_nom", type="string", length=50)
     * @Assert\NotBlank(message="error.input.blank")
     */
    private $nom;

    /**
     * @var string
     *
     * @ORM\Column(name="uti_prenom", type="string", length=50)
     * @Assert\NotBlank(message="error.input.blank")
     */
    private $prenom;

    /**
     * @var string
     *
     * @ORM\Column(name="uti_adresse", type="text")
     * @Assert\NotBlank(message="error.input.blank")
     */
    private $adresse;

    /**
     * @var string
     *
     * @ORM\Column(name="uti_telephone", type="string", length=13)
     * @Assert\NotBlank(message="error.input.blank")
     */
    private $telephone;

    /**
     * @var boolean
     *
     * @ORM\Column(name="uti_date_derniere_connexion", type="boolean", nullable=true)
     */
    private $dateDerniereConnexion;    

    /**
     * @var ArrayCollection
     * 
     * @ORM\ManyToMany(targetEntity="GroupeAutorisation", inversedBy="utilisateurs")
     * @ORM\JoinTable(name="mcp2_associe",
     *      joinColumns={@ORM\JoinColumn(name="ass_uti_id", referencedColumnName="uti_id")},
     *      inverseJoinColumns={@ORM\JoinColumn(name="ass_gra_id", referencedColumnName="gra_id")}
     *      )
     */
    private $groupesAutorisation;

    /**
     * @var ArrayCollection
     * 
     * @ORM\OneToMany(targetEntity="Notification", mappedBy="utilisateur", cascade={"persist", "remove"})
     */
    private $notifications;

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

        $this->groupesAutorisation = new \Doctrine\Common\Collections\ArrayCollection();
        $this->notifications = new \Doctrine\Common\Collections\ArrayCollection();
        $this->motDePasseExpire = False;

    }

    /**
     * Returns the username used to authenticate the user.
     *
     * @return string The username
     */
    public function getUsername() {
        return $this->username;
    }


    public function getSalt() {
        //return $this->salt;
        return null;

    }


    public function getPassword() {
        $this->password;
    }


    public function getRoles() {
        // special
        //return $this->groupesAutorisation->toArray();
        return array('ROLE_USER');
    }


    public function equals(UserInterface $user)
    {
            /* 
            if (!$account instanceof Account) {
                    return false;
            }

            if($this->password !== $user->getPassword()) {
                    return false;
            }

            if($this->getSalt() !== $user->getSalt()) {
                    return false;
            }

            if($this->getUsername() !== $user->getUsername()) {
                    return false;
            }

            return true; */

            return md5($this->getUsername()) == md5($user->getUsername());
    }

    /**
     * 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() {

    }

    /**
     * @see \Serializable::serialize()
     */
    public function serialize()
    {
        return serialize(array(
            $this->id,
        ));
    }

    /**
     * @see \Serializable::unserialize()
     */
    public function unserialize($serialized)
    {
        list (
            $this->id,
        ) = unserialize($serialized);
    }

    public function isAccountNonExpired()
    {
        return true;
    }

    public function isAccountNonLocked()
    {
        return true;
    }

    public function isCredentialsNonExpired()
    {
        return true;
    }

    public function isEnabled()
    {
        return $this->isActive;
    }    

    /**
     * Get id
     *
     * @return integer 
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set username 
     *
     * @param string $username 
     * @return Utilisateur
     */
    public function setUsername($nomUtilisateur)
    {
        $this->username = $nomUtilisateur;

        return $this;
    }

    /**
     * Set motDePasse
     *
     * @param string $motDePasse
     * @return Utilisateur
     */
    public function setPassword($motDePasse)
    {
        $this->password = $motDePasse;

        return $this;
    }


    /**
     * Set email
     *
     * @param string $email
     * @return Utilisateur
     */
    public function setEmail($email)
    {
        $this->email = $email;

        return $this;
    }

    /**
     * Get email
     *
     * @return string 
     */
    public function getEmail()
    {
        return $this->email;
    }


    /**
     * Get groupes
     *
     * @return \Doctrine\Common\Collections\Collection 
     */
    public function getGroupes()
    {
        return $this->groupes;
    }

    /**
     * Add notifications
     *
     * @param \ESIG\BBC\ManagerCP2Bundle\Entity\Notification $notifications
     * @return Utilisateur
     */
    public function addNotification(\ESIG\BBC\ManagerCP2Bundle\Entity\Notification $notifications)
    {
        $this->notifications[] = $notifications;

        return $this;
    }


    /**
     * Add groupesAutorisation
     *
     * @param \ESIG\BBC\ManagerCP2Bundle\Entity\GroupeAutorisation $groupesAutorisation
     * @return Utilisateur
     */
    public function addGroupesAutorisation(\ESIG\BBC\ManagerCP2Bundle\Entity\GroupeAutorisation $groupesAutorisation)
    {
        $this->groupesAutorisation[] = $groupesAutorisation;

        return $this;
    }

    /**
     * Remove groupesAutorisation
     *
     * @param \ESIG\BBC\ManagerCP2Bundle\Entity\GroupeAutorisation $groupesAutorisation
     */
    public function removeGroupesAutorisation(\ESIG\BBC\ManagerCP2Bundle\Entity\GroupeAutorisation $groupesAutorisation)
    {
        $this->groupesAutorisation->removeElement($groupesAutorisation);
    }

    /**
     * Get groupesAutorisation
     *
     * @return \Doctrine\Common\Collections\Collection 
     */
    public function getGroupesAutorisation()
    {
        return $this->groupesAutorisation;
    }

    /**
     * Set salt
     *
     * @param string $salt
     * @return Utilisateur
     */
    public function setSalt($salt)
    {
        $this->salt = $salt;

        return $this;
    }

    /**
     * Set isActive
     *
     * @param boolean $isActive
     * @return Utilisateur
     */
    public function setIsActive($isActive)
    {
        $this->isActive = $isActive;

        return $this;
    }

    /**
     * Get isActive
     *
     * @return boolean 
     */
    public function isActive()
    {
        return $this->isActive;
    }
}

(getSalt返回“null”只是为了确保他没有参与我的问题)

我的用户存储库:

<?php
namespace ESIG\BBC\ManagerCP2Bundle\Entity;

use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\NoResultException;
use ESIG\BBC\ManagerCP2Bundle\Entity\Notification;

/**
 * UtilisateurRepository
 *
 * This class was generated by the Doctrine ORM. Add your own custom
 * repository methods below.
 */
class UtilisateurRepository extends EntityRepository implements UserProviderInterface
{


    public function loadUserByUsername($username)
    {
        $q = $this
            ->createQueryBuilder('u')
            ->where('u.username = :username OR u.email = :email')
            ->setParameter('username', $username)
            ->setParameter('email', $username)
            ->getQuery();

        try {
            // La méthode Query::getSingleResult() lance une exception
            // s'il n'y a pas d'entrée correspondante aux critères
            $user = $q->getSingleResult();
        } catch (NoResultException $e) {
            throw new UsernameNotFoundException(sprintf('Unable to find an active admin AcmeUserBundle:User object identified by "%s".', $username), 0, $e);
        }

        return $user;
    }

    public function refreshUser(UserInterface $user)
    {
        $class = get_class($user);
        if (!$this->supportsClass($class)) {
            throw new UnsupportedUserException(
                sprintf(
                    'Instances of "%s" are not supported.',
                    $class
                )
            );
        }

        return $this->find($user->getId());

    }

    public function supportsClass($class)
    {
        return $this->getEntityName() === $class || is_subclass_of($class, $this->getEntityName());
    }
}

我的SecurityController:

<?php

namespace ESIG\BBC\ManagerCP2Bundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Component\Security\Core\SecurityContext;

class SecurityController extends Controller
{
    /**
     * @Template("ESIGBBCManagerCP2Bundle::menu.html.twig")
     */
    public function GenerateMenuAction()
    {
        return array();
    }

    /**
     * @Route("/login", name="_security_login")
     * @Template("ESIGBBCManagerCP2Bundle:Security:login.html.twig")
     */
    public function loginAction()
    {


        $request = $this->getRequest();
        $session = $request->getSession();

        // Récupère l'erreur de login si il y en a une
        if ($request->attributes->has(SecurityContext::AUTHENTICATION_ERROR)) {
            $error = $session->attributes->get(SecurityContext::AUTHENTICATION_ERROR);
        } else {
            $error = $session->get(SecurityContext::AUTHENTICATION_ERROR);
            $session->remove(SecurityContext::AUTHENTICATION_ERROR);
        }

        return array(
            'last_username' => $session->get(SecurityContext::LAST_USERNAME),
            'error'         => $error
        );
    }
     /**
     * @Route("/login_check", name="_security_check")
     * @Template("ESIGBBCManagerCP2Bundle:Security:login.html.twig")
     */   
    public function securityCheckAction()
    {


    }
    /**
     * @Route("/logout", name="_security_logout")
     * @Template("ESIGBBCManagerCP2Bundle:Security:login.html.twig")
     */
    public function logoutAction()
    {
        return array();
    }    


}

我的登录表单模板:

{% extends "ESIGBBCManagerCP2Bundle::ManagerCP2.html.twig" %}
{% block right %}
{{ error }}
    {% if error %}
        <div>{{ error.message }}</div>
    {% endif %}
        {{ test }}
    <form action="{{ path('_security_check') }}" method="post">


        <label for="username">Login :</label>
        <input type="text" id="username" name="_username" value="{{ last_username }}" title="{{ "login.mail.title" | trans }}" /><br />

        <label for="password" >Mot de passe :</label>
        <input type="password" id="password" name="_password" title="{{ "login.password.title" | trans }}" /><br />
        <input type="checkbox" id="remember_me" name="_remember_me" title="{{ "login.rememberme.title" | trans }}" checked />        <label for="remember_me" >Se souvenir de moi</label><br />

        {#
            Si vous voulez contrôler l'URL vers laquelle l'utilisateur est redirigé en cas de succès
            (plus de détails ci-dessous)
            <input type="hidden" name="_target_path" value="/account" />
        #}

        <button type="submit" name="login" title="{{ "login.submit.title" | trans }}">{{ "login.submit.value" | trans }}</button>
    </form>
{% endblock %}

最后:我的夹具

<?php

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
namespace ESIG\BBC\ManagerCP2Bundle\DataFixtures\ORM;

use Doctrine\Common\DataFixtures\FixtureInterface;
use Doctrine\Common\Persistence\ObjectManager;
use ESIG\BBC\ManagerCP2Bundle\Entity\Pompier;
use ESIG\BBC\ManagerCP2Bundle\Entity\Utilisateur;
use \Symfony\Component\Security\Core\Encoder\Pbkdf2PasswordEncoder;
use Symfony\Component\Security\Core\Encoder\MessageDigestPasswordEncoder;
/**
 * Description of LoadUserData
 *
 * @author noirv_000
 */
class LoadUserData implements FixtureInterface
{

    public function load(ObjectManager $manager)
    {              

       $pwd_encoder = new MessageDigestPasswordEncoder('sha512', true, 5000);


        // Super Administrateur
        $superAdmin = new Utilisateur();
        $superAdmin->setNom("Admin")
                    ->setPrenom("Super")
                    ->setUsername("super.admin")
                    ->setEmail("super@admin.foo")
                    ->setPassword($pwd_encoder->encodePassword("12345678", $superAdmin->getSalt()))
                    ->setAdresse("Chemin de l'administration")
                    ->setTelephone("0041000000000");
        $manager->persist($superAdmin);


        // Enregistre toutes les nouvelles entrées
        $manager->flush();
    }

}

请保存,T_T

2 个答案:

答案 0 :(得分:0)

首先检查UserAuthenticationProvider如何对密码进行编码并将其与datafixtures生成的密码进行比较

答案 1 :(得分:0)

试试这个:

$pwd_encoder = new EncoderFactory(array('Symfony\Component\Security\Core\User\UserInterface' => new MessageDigestPasswordEncoder('sha1',true,500)));

 // Super Administrateur
    $superAdmin = new Utilisateur();
    $superAdmin->setNom("Admin")
                ->setPrenom("Super")
                ->setUsername("super.admin")
                ->setEmail("super@admin.foo")
                ->setPassword($pwd_encoder->getEncoder($superAdmin)->encodePassword("12345678", $superAdmin->getSalt()))
                ->setAdresse("Chemin de l'administration")
                ->setTelephone("0041000000000");