此刻我完全迷失了,两天后我试图弄清楚为什么我总是在我的登录表单上获得“坏凭据”响应。
我使用了如何从数据库教程中加载安全用户。
有什么方法可以知道他在比较什么以获得“坏凭据”错误?
转储的错误:
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());
}
}
我的安全控制器:
<?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