Symfony 2.3 Bad Credentials 自定义提供程序
Posted
技术标签:
【中文标题】Symfony 2.3 Bad Credentials 自定义提供程序【英文标题】:Symfony 2.3 Bad Credentials Custom provider 【发布时间】:2013-10-23 04:49:04 【问题描述】:此刻我完全迷失了,两天后我试图弄清楚为什么我总是在我的登录表单上获得“错误凭据”响应。
我用过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());
我的安全控制器:
<?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
【问题讨论】:
【参考方案1】:首先检查 UserAuthenticationProvider 如何对您的密码进行编码,并将其与 datafixtures 生成的密码进行比较
【讨论】:
【参考方案2】:试试这个:
$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");
【讨论】:
以上是关于Symfony 2.3 Bad Credentials 自定义提供程序的主要内容,如果未能解决你的问题,请参考以下文章
Nginx 用 502 Bad Gateway 覆盖一般的 symfony 错误
Ngrok 到 dockerised symfony 5 的隧道以 502 bad gateway 结束
Symfony4 + jwt-auth rescipe 总是返回 "code":401,"message":"Bad credentials"