I'm trying to follow the documentation but can't get it to work. I keep getting "Bad credentials" when trying to use the login form.
Here is my security.yml file
security:
encoders:
MyCompany\MyPoroject\UserBundle\Entity\User:
algorithm: sha1
encode_as_base64: false
iterations: 1
role_hierarchy:
ROLE_ADMIN: ROLE_USER
ROLE_SUPER_ADMIN: [ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]
providers:
administrators:
entity: { class: MyCompanyMyProjectUserBundle:User, property: username }
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
secured_area:
pattern: ^/
anonymous: ~
form_login:
login_path: login
check_path: login_check
access_control:
- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/admin, roles: ROLE_ADMIN }
This is the code i've used to create some dummy users
$factory = $this->get('security.encoder_factory');
$user = new User;
$encoder = $factory->getEncoder($user);
$password = $encoder->encodePassword('testing', $user->getSalt());
$user->setPassword($password)
->setEmail('test#gmail.com')
->setUsername('testing');
$em = $this->getDoctrine()->getManager();
$em->persist($user);
$em->flush();
Here is my User class
class User implements UserInterface, \Serializable
{
private $id;
private $username;
private $salt;
private $password;
private $email;
private $isActive;
public function __construct()
{
$this->isActive = true;
$this->salt = md5(uniqid(null, true));
}
/**
* Returns the roles granted to the user.
*
* <code>
* public function getRoles()
* {
* return array('ROLE_USER');
* }
* </code>
*
* Alternatively, the roles might be stored on a ``roles`` property,
* and populated in any number of different ways when the user object
* is created.
*
* #return Role[] The user roles
*/
public function getRoles()
{
return ['ROLE_USER'];
}
/**
* Returns the password used to authenticate the user.
*
* This should be the encoded password. On authentication, a plain-text
* password will be salted, encoded, and then compared to this value.
*
* #return string The password
*/
public function getPassword()
{
$this->password;
}
/**
* Returns the salt that was originally used to encode the password.
*
* This can return null if the password was not encoded using a salt.
*
* #return string|null The salt
*/
public function getSalt()
{
$this->salt;
}
/**
* Returns the username used to authenticate the user.
*
* #return string The username
*/
public function getUsername()
{
return $this->username;
}
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set username
*
* #param string $username
* #return User
*/
public function setUsername($username)
{
$this->username = $username;
return $this;
}
/**
* Set salt
*
* #param string $salt
* #return User
*/
public function setSalt($salt)
{
$this->salt = $salt;
return $this;
}
/**
* Set password
*
* #param string $password
* #return User
*/
public function setPassword($password)
{
$this->password = $password;
return $this;
}
/**
* Set email
*
* #param string $email
* #return User
*/
public function setEmail($email)
{
$this->email = $email;
return $this;
}
/**
* Get email
*
* #return string
*/
public function getEmail()
{
return $this->email;
}
/**
* Set is_active
*
* #param boolean $isActive
* #return User
*/
public function setIsActive($isActive)
{
$this->isActive = $isActive;
return $this;
}
/**
* Get is_active
*
* #return boolean
*/
public function getIsActive()
{
return $this->isActive;
}
/**
* (PHP 5 >= 5.1.0)<br/>
* String representation of object
* #link http://php.net/manual/en/serializable.serialize.php
* #return string the string representation of the object or null
*/
public function serialize()
{
return serialize(array(
$this->id,
$this->username,
$this->salt,
$this->password,
));
}
/**
* (PHP 5 >= 5.1.0)<br/>
* Constructs the object
* #link http://php.net/manual/en/serializable.unserialize.php
* #param string $serialized <p>
* The string representation of the object.
* </p>
* #return void
*/
public function unserialize($serialized)
{
list (
$this->id,
$this->username,
$this->salt,
$this->password,
) = unserialize($serialized);
}
/**
* 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()
{
}
}
My Security controller
class SecurityController extends Controller
{
public function loginAction(Request $request)
{
$session = $request->getSession();
// get the login error if there is one
if ($request->attributes->has(SecurityContext::AUTHENTICATION_ERROR)) {
$error = $request->attributes->get(
SecurityContext::AUTHENTICATION_ERROR
);
} else {
$error = $session->get(SecurityContext::AUTHENTICATION_ERROR);
$session->remove(SecurityContext::AUTHENTICATION_ERROR);
}
return $this->render(
'MyCompanyMyProjectUserBundle:Security:login.html.twig',
array(
// last username entered by the user
'last_username' => $session->get(SecurityContext::LAST_USERNAME),
'error' => $error,
)
);
}
public function adminAction()
{
return $this->render('MyCompanyMyProjectUserBundle:Security:admin.html.twig');
}
}
This is the record in the database i'm attempting to login with using testing as both the username and password.
id: 3
username(25): testing
salt(32): 87a449194ebfe80bfa9f59da53dab0ea
password(64): dc724af18fbdd4e59189f5fe768a5f8311527050
email(60): test#gmail.com
Probably you missed return statement in getSalt() and getPassword() methods
Related
I'm stack heeeere in security, help me please!!
I got this error 2 days ago and couldn't solve it : "The token storage contains no authentication token. One possible reason may be that there is no firewall configured for this URL." My login in the index page, and the login and login_check are in the same function (indexAction).This is my security.yml file, my controller, and my entity "user" :
# you can read more about security in the related section of the documentation
# http://symfony.com/doc/current/book/security.html
security:
# http://symfony.com/doc/current/book/security.html#encoding-the-user-s-password
encoders:
#Symfony\Component\Security\Core\User\User: plaintext
CNAM\CMSBundle\Entity\user: bcrypt
# http://symfony.com/doc/current/book/security.html#hierarchical-roles
role_hierarchy:
ROLE_ADMIN: ROLE_USER
ROLE_SUPER_ADMIN: [ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]
# http://symfony.com/doc/current/book/security.html#where-do-users-come-from-user-providers
providers:
in_memory:
memory:
users:
user: { password: userpass, roles: [ 'ROLE_USER' ] }
admin: { password: adminpass, roles: [ 'ROLE_ADMIN' ] }
database:
entity:
class: CNAM\CMSBundle\Entity\user
property: username
# the main part of the security, where you can set up firewalls
# for specific sections of your app
firewalls:
# disables authentication for assets and the profiler, adapt it according to your needs
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
admin_area:
pattern: ^/admin
form_login:
check_path: _default_index
login_path: _default_index
access_control:
#- { path: ^/, roles: IS_AUTHENTICATED_ANONYMOUSLY}
- { path: ^/admin, roles: ROLE_ADMIN}
<?php
namespace CNAM\CMSBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Component\HttpFoundation\Request;
use CNAM\CMSBundle\Entity\user;
use CNAM\CMSBundle\Entity\userprof;
use CNAM\CMSBundle\Entity\profil;
use CNAM\CMSBundle\Entity\privilege;
use Symfony\Component\BrowserKit\Response;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilder;
use Symfony\Component\Security\Core\Security;
class DefaultController extends Controller
{
/**
* #Route("/")
* #Template()
*/
public function indexAction(Request $request)
{
$user = new user();
$form = $this->createFormBuilder($user)
->add('id', 'text',array('attr'=>array('name'=>'login_user','required'=>'required',
'maxlength'=>'255','placeholder'=>'Votre matricule','id'=>'login_user')))
->add('password', 'password',array('attr'=>array('name'=>'login_password','required'=>'required',
'maxlength'=>'20','placeholder'=>'Mot de passe','id'=>'login_password')))
->add('Connexion', 'submit',array('attr'=>array('class'=>'btn btn-primary btn-block rounded_btn','id'=>'login_btn',
'style'=>"width:8vw;height:5vh;padding:0px 0px; position:relative;left:5vmin;top:1vmin;font-size:2vmin;")))
->getForm();
$form->handleRequest($request);
//$b_search=$this->get('session')->get('search');
$id = $request->request->get('id');
$session = $request->getSession();
if ($form->isValid()) {
$data = $form->getData();
$repository = $this
->getDoctrine()
->getManager()
->getRepository("CNAMCMSBundle:user");
$rep = $this
->getDoctrine()
->getManager()
->getRepository("CNAMCMSBundle:userprof");
$search = $repository->find($data);
$p_search=$rep->find($data);
$helper = $this->get('security.authentication_utils');
if (!$search) {
//throw $this->createNotFoundException('Utilisateur introuvable!');
}
else {
//$session=$this->get("session");
//$session->start();
// $session->set('search', $search);
$user->setEtat(1);
$em = $this->getDoctrine()->getManager();
$user=$em->merge($user);
$em->flush();
$id_prof=$p_search->getIdProfil();
switch ($id_prof)
{
case 1: return $this->redirect($this->generateUrl('cnam_cms_default_webmaster'),301);break;
case 2: $user->setRole("ROLE_ADMIN");$em = $this->getDoctrine()->getManager();$user=$em->merge($user);
$em->flush();return $this->redirect($this->generateUrl('cnam_cms_default_admin'),301);break;
case 3: return $this->redirect($this->generateUrl('cnam_cms_default_sup_med'),301);break;
case 4: return $this->redirect($this->generateUrl('cnam_cms_default_med'),301);break;
case 5: return $this->redirect($this->generateUrl('cnam_cms_default_gest_mp'),301);break;
}
}
//return $this->render('CNAMCMSBundle:Default:profile.html.twig', array(
//'search' => $search,
//'b_search'=>$b_search
// ));
}
return array('form'=>$form->createView());
}
/**
* #Route("/admin")
* #Template()
*/
public function adminAction()
{
return $this->render('CNAMCMSBundle:Default:admin.html.twig', array());
}
/**
* #Route("/admin/gestEtat",name="gestEtat")
* #Template()
*/
public function gestEtatAction()
{
return $this->render('CNAMCMSBundle:Default:gestEtat.html.twig', array());
}
}
<?php
namespace CNAM\CMSBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Security\Core\User\UserInterface;
/**
* user
*
* #ORM\Table(name="user")
* #ORM\Entity
*/
class user implements UserInterface
{
/**
* #var integer
*#Assert\NotBlank()
* #ORM\Column(name="id", type="integer")
* #ORM\Id
*/
private $id;
/**
* #var string
*#Assert\NotBlank()
* #ORM\Column(name="password", type="string", length=40)
*/
private $password;
/*
* #ORM\ManyToOne(targetEntity="profil" , inversedBy="users")
* #ORM\JoinColumn(name="id_profil", referencedColumnName="id_profil")
*/
private $profil;
public function __construct()
{
$this->profil = new ArrayCollection();
}
/**
* #var boolean
*
* #ORM\Column(name="etat", type="boolean")
*/
private $etat;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set id
*
* #param integer $id
* #return user
*/
public function setId($id)
{
$this->id = $id;
return $this;
}
/**
* Set password
*
* #param string $password
* #return user
*/
public function setPassword($password)
{
$this->password = $password;
return $this;
}
/**
* Get password
*
* #return string
*/
public function getPassword()
{
return $this->password;
}
/**
* Set etat
*
* #param boolean $etat
* #return user
*/
public function setEtat($etat)
{
$this->etat = $etat;
return $this;
}
/**
* Get etat
*
* #return boolean
*/
public function getEtat()
{
return $this->etat;
}
/**
* Get profil
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getProfil()
{
return $this->profil;
}
/**
* Add profil
*
* #param \CNAM\CMSBundle\Entity\user $profil
* #return user
*/
public function addProfil(\CNAM\CMSBundle\Entity\profil $profil)
{
$this->profil[] = $profil;
return $this;
}
/**
* Remove profil
*
* #param \CNAM\CMSBundle\Entity\profil $profil
*/
public function removeProfil(\CNAM\CMSBundle\Entity\profil $profil)
{
$this->profil->removeElement($profil);
}
public function getUsername()
{
return $this->id;
}
public function getRoles()
{
return array('ROLE_USER');
}
public function getSalt()
{
return null;
}
public function eraseCredentials()
{
}
public function equals(UserInterface $user)
{
return $user->getId() == $this->getId();
}
}
I have a Invalid credentials error when I'm trying to load my user form the database.
Here is my security.yml
security:
providers:
database:
entity: { class: AppBundle\Entity\User, property: username }
encoders:
AppBundle\Entity\User: plaintext
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
anonymous: ~
# pattern: ^/
form_login:
login_path: /login
check_path: /login_check
# default_target_path: /admin
provider: database
logout:
path: /logout
target: /login
My User Entity:
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\UserInterface;
/**
* User
*
* #ORM\Table(name="user")
* #ORM\Entity(repositoryClass="AppBundle\Repository\UserRepository")
*/
class User implements UserInterface
{
/**
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="string", unique=true)
*/
private $username;
/**
* #ORM\Column(type="string")
*/
private $password;
/**
* #return mixed
*/
public function getId()
{
return $this->id;
}
/**
* Returns the password used to authenticate the user.
*
* This should be the encoded password. On authentication, a plain-text
* password will be salted, encoded, and then compared to this value.
*
* #return string The password
*/
public function getPassword()
{
return $this->password;
}
/**
* Set password
*
* #param string $password
*
* #return User
*/
public function setPassword($password)
{
$this->password = $password;
return $this;
}
/**
* Returns the salt that was originally used to encode the password.
*
* This can return null if the password was not encoded using a salt.
*
* #return string|null The salt
*/
public function getSalt()
{
}
/**
* Returns the username used to authenticate the user.
*
* #return string The username
*/
public function getUsername()
{
return $this->getUsername();
}
/**
* Set username
*
* #param string $username
*
* #return User
*/
public function setUsername($username)
{
$this->username = $username;
return $this;
}
/**
* 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()
{
// TODO: Implement eraseCredentials() method.
}
/**
* Returns the roles granted to the user.
*
* <code>
* public function getRoles()
* {
* return array('ROLE_USER');
* }
* </code>
*
* Alternatively, the roles might be stored on a ``roles`` property,
* and populated in any number of different ways when the user object
* is created.
*
* #return (Role|string)[] The user roles
*/
public function getRoles()
{
// TODO: Implement getRoles() method.
}
}
My Controllers:
/**
* #Route("/login", name="login")
*/
public function loginAction(Request $request)
{
$authenticationUtils = $this->get('security.authentication_utils');
// get the login error if there is one
$error = $authenticationUtils->getLastAuthenticationError();
// last username entered by the user
$lastUsername = $authenticationUtils->getLastUsername();
$form = $this->createForm(LoginType::class, array(
'_username' => $lastUsername,
));
return $this->render(':back/security:login.html.twig', array(
'error' => $error,
'form' => $form->createView(),
));
}
/**
* #Route("/login_check", name="login_check")
*/
public function loginCheckAction(){}
I don't understand why it does not work. I have tried to follow the documentation and make it very simple.
The user is in my database and the password is plaintext.
What did I do wrong?
I am trying to implement a login system with Symfony2. I am implementing the AdvancedUserInterface for my User entity, and keep getting the following error when I try to log in. Any help is appreciated.
Error:
$user must be an instanceof UserInterface, an object implementing a __toString method, or a primitive string.
User Entity:
<?php
namespace Flc\UserBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\AdvancedUserInterface;
use Serializable;
/**
* User
*
* #ORM\Table(name="users")
* #ORM\Entity(repositoryClass="Flc\UserBundle\Entity\UserRepository")
*/
class User implements AdvancedUserInterface, Serializable {
/**
* #var integer
*
* #ORM\Column(name="userId", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $userId;
/**
* #var string
*
* #ORM\Column(name="userEmail", type="string", length=50)
*/
private $userEmail;
/**
* #var string
*
* #ORM\Column(name="userName", type="string", length=20)
*/
private $userName;
/**
* #var string
*
* #ORM\Column(name="userPassword", type="string", length=60)
*/
private $userPassword;
/**
* #var string
*
* #ORM\Column(name="userSalt", type="string", length=60, nullable=true)
*/
private $userSalt;
/**
* #var string
*
* #ORM\Column(name="userFirstName", type="string", length=40)
*/
private $userFirstName;
/**
* #var string
*
* #ORM\Column(name="userLastName", type="string", length=40)
*/
private $userLastName;
/**
* #var string
*
* #ORM\Column(name="userPhone", type="string", length=10)
*/
private $userPhone;
/**
* #var \DateTime
*
* #ORM\Column(name="created", type="datetime")
*/
private $created;
/**
* #var boolean
*
* #ORM\Column(name="isActive", type="boolean")
*/
private $isActive;
/**
* #var array
*
* #ORM\Column(name="roles", type="json_array", nullable=true)
*/
private $roles;
#########################
## GETTER - SETTER FUNCTIONS ##
#########################
/**
* Get userId
*
* #return integer
*/
public function getUserId() {
return $this->userId;
}
/**
* Set userEmail
*
* #param string $userEmail
* #return User
*/
public function setUserEmail($userEmail) {
$this->userEmail = $userEmail;
return $this;
}
/**
* Get userEmail
*
* #return string
*/
public function getUserEmail() {
return $this->userEmail;
}
/**
* Set userName
*
* #param string $userName
* #return User
*/
public function setUserName($userName) {
$this->userName = $userName;
return $this;
}
/**
* Get userName
*
* #return string
*/
public function getUserName() {
return $this->userName;
}
/**
* Set userPassword
*
* #param string $userPassword
* #return User
*/
public function setUserPassword($userPassword) {
$this->userPassword = $userPassword;
return $this;
}
/**
* Get userPassword
*
* #return string
*/
public function getUserPassword() {
return $this->userPassword;
}
/**
* Set userSalt
*
* #param string $userSalt
* #return User
*/
public function setUserSalt($userSalt) {
$this->userSalt = $userSalt;
return $this;
}
/**
* Get userSalt
*
* #return string
*/
public function getUserSalt() {
return $this->userSalt;
}
/**
* Set userFirstName
*
* #param string $userFirstName
* #return User
*/
public function setUserFirstName($userFirstName) {
$this->userFirstName = $userFirstName;
return $this;
}
/**
* Get userFirstName
*
* #return string
*/
public function getUserFirstName() {
return $this->userFirstName;
}
/**
* Set userLastName
*
* #param string $userLastName
* #return User
*/
public function setUserLastName($userLastName) {
$this->userLastName = $userLastName;
return $this;
}
/**
* Get userLastName
*
* #return string
*/
public function getUserLastName() {
return $this->userLastName;
}
/**
* Set userPhone
*
* #param string $userPhone
* #return User
*/
public function setUserPhone($userPhone) {
$this->userPhone = $userPhone;
return $this;
}
/**
* Get userPhone
*
* #return string
*/
public function getUserPhone() {
return $this->userPhone;
}
/**
* Set created
*
* #param \DateTime $created
* #return User
*/
public function setCreated($created) {
$this->created = $created;
return $this;
}
/**
* Get created
*
* #return \DateTime
*/
public function getCreated() {
return $this->created;
}
/**
* Set isActive
*
* #param boolean $isActive
* #return User
*/
public function setIsActive($isActive) {
$this->isActive = $isActive;
return $this;
}
/**
* Get isActive
*
* #return boolean
*/
public function getIsActive() {
return $this->isActive;
}
/**
* Set roles
*
* #param boolean $roles
* #return User
*/
public function setRoles(array $roles) {
$this->roles = $roles;
return $this;
}
#############################################
## USER INTERFACE FUNCTIONS IMPLEMENTATION ##
#############################################
public function getRoles() {
#return $this->roles;
$roles = $this->roles;
$roles[] = 'ROLE_USER';
return array_unique($roles);
}
public function eraseCredentials() {
//will be implemented
}
public function getSalt() {
return $this->getUserSalt();
}
public function getPassword() {
return $this->getUserPassword();
}
public function isAccountNonExpired() {
return true;
}
public function isAccountNonLocked() {
return true;
}
public function isCredentialsNonExpired() {
return true;
}
public function isEnabled() {
return $this->isActive;
}
#####################################################
## SERIALIZABLE INTERFACE FUNCTIONS IMPLEMENTATION ##
#####################################################
public function serialize() {
return serialize(array(
$this->userId,
$this->userName,
$this->userPassword
));
}
public function unserialize($serialized) {
list(
$this->userId,
$this->userName,
$this->userPassword) = unserialize($serialized);
}
}
User Repository:
<?php
namespace Flc\UserBundle\Entity;
use Doctrine\ORM\EntityRepository;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
/**
* UserRepository
*
* This class was generated by the Doctrine ORM. Add your own custom
* repository methods below.
*/
class UserRepository extends EntityRepository implements UserProviderInterface {
public function findOneByUsernameOrEmail($username) {
return $this->createQueryBuilder('u')
->andWhere('u.userName = :username OR u.userEmail = :email')
->setParameter('username', $username)
->setParameter('email', $username)
->getQuery()
->getOneOrNullResult();
}
public function loadUserByUsername($username) {
//$user = $this->findOneByUsernameOrEmail($username);
$user = $this->findOneBy(array("userName"=>$username));
if (!$user) {
throw new UsernameNotFoundException('No user found for ' . $username);
}
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
));
}
if (!$refreshedUser = $this->find($user->getUserId())) {
throw new UsernameNotFoundException(sprintf('User with id %s not found'), json_encode($refreshedUser));
}
}
public function supportsClass($class) {
return $this->getEntityName() === $class || is_subclass_of($class, $this->getEntityName());
}
}
Security YML:
security:
encoders:
Flc\UserBundle\Entity\User: bcrypt
role_hierarchy:
ROLE_ADMIN: ROLE_USER
ROLE_SUPER_ADMIN: [ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]
providers:
flc_users:
entity: { class: FlcUserBundle:User }
firewalls:
secured_area:
pattern: ^/
form_login:
login_path: login_form
check_path: login_check
logout:
path: logout
target: /
anonymous: ~
access_control:
- { path: ^/app, roles: ROLE_USER }
try adding __toString method on your User entity:
public function __toString() {
return (string) $this->getUsername();
}
In User Repository you need to replace :
public function findOneByUsernameOrEmail($username) {
return $this->createQueryBuilder('u')
->andWhere('u.userName = :username OR u.userEmail = :email')
->setParameter('username', $username)
->setParameter('email', $username)
->getQuery()
->getOneOrNullResult();
}
public function loadUserByUsername($username) {
//$user = $this->findOneByUsernameOrEmail($username);
$user = $this->findOneBy(array("userName"=>$username));
if (!$user) {
throw new UsernameNotFoundException('No user found for ' . $username);
}
return $user;
}
with :
public function loadUserByUsername($username)
{
$q = $this
->createQueryBuilder('u')
->where('u.username = :username OR u.email = :email')
->setParameter('username', $username)
->setParameter('email', $username)
->getQuery();
try {
$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;
}
I am having some trouble with login and authentication in Symfony2. The exception is "$user must be an instanceof UserInterface, an object implementing a __toString method, or a primitive string."
Debugging my code I could notice that the user I am trying to log in my application can get authenticated successfully (app/log/dev.log) but the credentials var is null:
The user variable from AbstractToken has the user data from database.
I continue debugging in the ContextListener->refreshUser function and I get these values:
Everything has the value null and on the Symfony\Bridge\Doctrine\Security\User\EntityUserProvider->refreshUser function returns the variable $refreshedUser as null, so when the function $token->setUser($refreshedUser) on the ContextListener class fails and throws the exception.
I write down my security.yml and my entities I am using:
security.yml:
security:
encoders:
Pladuch\BackBundle\Entity\BaseUser:
algorithm: sha512
encode_as_base64: false
iterations: 1
providers:
sga:
entity: { class: 'PladuchBackBundle:Usuario', property: username }
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
sga:
pattern: ^/gestion
anonymous: ~
form_login:
login_path: pladuch_login_sga
check_path: pladuch_login_check
default_target_path: pladuch_sga_index
csrf_provider: form.csrf_provider
provider: sga
logout:
path: pladuch_logout_sga
target: pladuch_login_sga
access_control:
- { path: ^/gestion/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/gestion, roles: ROLE_ADMIN }
Abstract class BaseUser:
<?php
namespace Pladuch\BackBundle\Entity;
use Symfony\Component\Security\Core\User\AdvancedUserInterface;
abstract class BaseUser implements AdvancedUserInterface, \Serializable
{
protected $id;
protected $salt;
protected $username;
protected $password;
public function __construct()
{
$this->isActive = true;
$this->salt = $this->generateSalt();
}
public function serialize()
{
return serialize(array($this->id, $this->username, $this->password));
}
public function unserialize($serialized)
{
list($this->id, $this->username, $this->password) = unserialize($serialized);
}
public function getRoles()
{
return array('ROLE_ADMIN');
}
public function getPassword()
{
return $this->password;
}
public function setPassword($password)
{
$this->password = $password;
}
public function getUsername()
{
return $this->username;
}
public function eraseCredentials()
{
}
public function setSalt($salt)
{
$this->salt = $salt;
return $this;
}
public function getSalt()
{
return $this->salt;
}
public function generateSalt()
{
return base_convert(sha1(uniqid(mt_rand(), true)), 16, 36);
}
public function isAccountNonExpired()
{
return true;
}
public function isAccountNonLocked()
{
return true;
}
public function isCredentialsNonExpired()
{
return true;
}
public function isEnabled()
{
return true;
}
}
Class Usuario:
<?php
namespace Pladuch\BackBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Usuario
*
* #ORM\Table(name="usuario",
* uniqueConstraints={
* #ORM\UniqueConstraint(name="username", columns={"username"})
* },
* indexes={#ORM\Index(name="FK_USUARIO_ROL", columns={"rol_id"})})
* #ORM\Entity(repositoryClass="Pladuch\BackBundle\Repository\UsuarioRepository")
*/
class Usuario extends BaseUser
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer", nullable=false)
* #ORM\Id()
* #ORM\GeneratedValue(strategy="IDENTITY")
*/
protected $id;
/**
* #var string
*
* #ORM\Column(name="username", type="string", length=255, nullable=false)
*/
protected $username;
/**
* #var string
*
* #ORM\Column(name="password", type="string", length=1024, nullable=false)
*/
protected $password;
/**
* #var string
*
* #ORM\Column(name="salt", type="string", length=1024, nullable=false)
*/
protected $salt;
/**
* #var string
*
* #ORM\Column(name="email", type="string", length=255, nullable=false)
*/
protected $email;
/**
* #var Rol
*
* #ORM\ManyToOne(targetEntity="Rol", inversedBy="id")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="rol_id", referencedColumnName="id")
* })
*/
protected $rol;
/**
* #var bool
*
* #ORM\Column(name="activo", type="boolean", nullable=true)
*/
protected $activo = true;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set username
*
* #param string $username
* #return Usuario
*/
public function setUsername($username)
{
$this->username = $username;
return $this;
}
/**
* Get username
*
* #return string
*/
public function getUsername()
{
return $this->username;
}
/**
* Set password
*
* #param string $password
* #return Usuario
*/
public function setPassword($password)
{
$this->password = $password;
return $this;
}
/**
* Get password
*
* #return string
*/
public function getPassword()
{
return $this->password;
}
/**
* Set salt
*
* #param string $salt
* #return Usuario
*/
public function setSalt($salt)
{
$this->salt = $salt;
return $this;
}
/**
* Get salt
*
* #return string
*/
public function getSalt()
{
return $this->salt;
}
/**
* Set email
*
* #param string $email
* #return Usuario
*/
public function setEmail($email)
{
$this->email = $email;
return $this;
}
/**
* Get email
*
* #return string
*/
public function getEmail()
{
return $this->email;
}
/**
* Set rol
*
* #param Rol $rol
* #return Usuario
*/
public function setRol(Rol $rol = null)
{
$this->rol = $rol;
return $this;
}
/**
* Get rol
*
* #return Rol
*/
public function getRol()
{
return $this->rol;
}
/**
* #return array|\Symfony\Component\Security\Core\Role\Role[]
*/
public function getRoles()
{
return array($this->getRol()->getRol());
}
/**
* Set activo
*
* #param $activo
* #return $this
*/
public function setActivo($activo)
{
$this->activo = $activo;
return $this;
}
/**
* Get activo
*
* #return bool
*/
public function getActivo()
{
return $this->activo;
}
}
The UsuarioRepository where I implements the three functions loadUserByUsername, refreshUser and supportsClass:
class UsuarioRepository extends EntityRepository implements UserProviderInterface
{
public function loadUserByUsername($username)
{
$q = $this->createQueryBuilder('u')
->where('u.username = :username')
->setParameter('username', $username)
->getQuery();
try {
$user = $q->getSingleResult();
} catch (NoResultException $e) {
$message = sprintf('Unable to find an active Usuario object identified by %s', $username);
throw new UsernameNotFoundException($message, 0, $e);
}
return $user;
}
public function refreshUser(UserInterface $userInterface)
{
$class = get_class($userInterface);
if (! $this->supportsClass($class)) {
throw new UnsupportedUserException(sprintf('Instances of %s are not suppoted', $class));
}
}
public function supportsClass($class)
{
return $this->getEntityName() === $class || is_subclass_of($class, $this->getEntityName());
}
}
Thank you for your help.
Kind regards.
P.S: I am using Symfony 2.5.6
Ok, I forgot to add the return sentence on refreshUser function in my repository...
return $this->find($userInterface->getId());
or
return $userInterface;
$userInterface has the authenticated user so I didn't need the $this->find() method. That solved everything
I'm trying since 3 hours to install and configure FOSuser, which many developpers adviced me to use it.I wanted actually to make a normal login form without to use FOS but I had a lot of problems.I followed all steps in the documentation. the installation was ok , the configuration also but everytime when I try to log in , it shows "Bad credentials".So i find somehow this command that I executed :php app/console fos:user:create i give name-email-password. it work somehow but only with what i write, I mean when I register user in my registration form and try to log in it shows "Bad credentials".I hope that I was clear else please tell me what do you need to know
Here are my Users.php where i have all my users info to login...
namespace test\indexBundle\Document;
use FOS\UserBundle\Model\User as BaseUser;
use Symfony\Component\Security\Core\User\UserInterface;
use Doctrine\ODM\MongoDB\Mapping\Annotations as MongoDB;
/**
*
* #MongoDB\Document
*/
class Users extends BaseUser
{
/**
* #MongoDB\Id
*/
protected $id;
/**
* #MongoDB\String
*/
protected $userId;
/**
* #MongoDB\String
*/
protected $userEmail;
/**
* #MongoDB\String
*/
protected $userPassword;
/**
* #MongoDB\String
*/
protected $salt;
/**
* #MongoDB\Int
*/
protected $isActive;
public function __construct()
{
parent::__construct();
$this->isActive = true;
$this->salt = md5(uniqid(null, true));
}
/**
* Set id
*
* #param id $id
*/
public function setId($id)
{
$this->id = $id;
}
/**
* Get id
*
* #return id $id
*/
public function getId()
{
return $this->id;
}
/**
* Set userId
*
* #param string $userId
*/
public function setUserId()
{
$this->userId = $this->salt;
}
/**
* Get userId
*
* #return string $userId
*/
public function getUserId()
{
return $this->userId;
}
/**
* Set userName
*
* #param string $userName
*/
public function setUserName($userName)
{
$this->userName = $userName;
}
/**
* Get userName
*
* #return string $userName
*/
public function getUserName()
{
return $this->username;
}
/**
* Set userEmail
*
* #param string $userEmail
*/
public function setUserEmail($userEmail)
{
$this->userEmail = $userEmail;
}
/**
* Get userEmail
*
* #return string $userEmail
*/
public function getUserEmail()
{
return $this->userEmail;
}
/**
* Set userPassword
*
* #param string $userPassword
*/
public function setPassword($userPassword)
{
$this->userPassword = $userPassword;
}
/**
* Get userPassword
*
* #return string $userPassword
*/
public function getPassword()
{
return $this->userPassword;
}
/**
* #inheritDoc
*/
public function getSalt()
{
return '';
}
/**
* #inheritDoc
*/
public function getRoles()
{
return array('ROLE_USER');
}
/**
* #inheritDoc
*/
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);
}
}
and here my security.yml:
jms_security_extra:
secure_all_services: false
expressions: true
security:
encoders:
FOS\UserBundle\Model\UserInterface: sha512
test\indexBundle\Document\Users:
algorithm: sha1
encode_as_base64: false
iterations: 1
role_hierarchy:
ROLE_ADMIN: ROLE_USER
ROLE_SUPER_ADMIN: [ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]
providers:
fos_userbundle:
id: fos_user.user_provider.username_email
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
pattern: ^/
anonymous: true
form_login:
check_path: /login_check
login_path: /login
provider: fos_userbundle
post_only: true
use_forward: false
username_parameter: email
password_parameter: password
failure_path: null
failure_forward: false
target_path_parameter: redirect_url
logout:
path: /logout
target: /blog
access_control:
- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
and login function:
public function loginAction()
{
$request = $this->getRequest();
$session = $request->getSession();
if ($this->get('security.context')->isGranted('IS_AUTHENTICATED_FULLY'))
{
return $this->redirect($this->generateUrl('index_homepage'));
}
if ($request->attributes->has(SecurityContext::AUTHENTICATION_ERROR))
{
$error = $request->attributes->get(SecurityContext::AUTHENTICATION_ERROR);
}
else
{
$error = $session->get(SecurityContext::AUTHENTICATION_ERROR);
$session->remove(SecurityContext::AUTHENTICATION_ERROR);
}
return $this->render('indexBundle:index:logIn.html.twig', array(
'last_username' => $session->get(SecurityContext::LAST_USERNAME),
'error' => $error,
));
}
I might be wrong but I think FOSUserBundle requires a user to be activated after it's been created if you use the form registration, it's send out and email with a link I believe. I think you can use app/console fos:user:activate to activate if there is no email.