Symfony2 authentification issue
Trying to implement role-based user access in Symfony2, but somehow Symfony2 does not fetch user from the database. All I get is Bad Credentials error. When I do try to log in as in-memory user - it works fine. Am I missing something?
My security.yml
security:
encoders:
Symfony\Component\Security\Core\User\User:
algorithm: sha512
encode-as-base64: true
iterations: 3
role_hierarchy:
ROLE_ADMIN: ROLE_USER
ROLE_SUPER_ADMIN: [ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]
providers:
in_memory:
users:
user: { password: userpass, roles: [ 'ROLE_USER' ] }
main:
entity: { class: Web20CMSBundle:User, property: username }
firewalls:
secured_area:
pattern: /admin.*|/login_check
anonymous: ~
form_login:
check_path: /login_check
login_path: /login
logout: { path: /admin/logout, target: / }
security: true
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
access_control:
- { path: /admin/.*, role: ROLE_ADMIN }
- { path: /.*, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: /login.*, role: IS_AUTHENTICATED_ANONYMOUSLY }
my routing.yml
_security_login:
pattern: /login
defaults: { _controller: Web20CMSBundle:Security:login }
_security_check:
pattern: /login_check
_security_logout:
pattern: /admin/logout
index:
pattern: /
defaults: { _controller: JutaShopBundle:Default:index }
my Role entity
<?php
namespace Web20\CMSBundle\Entity;
use Symfony\Component\Security\Core\Role\RoleInterface;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
* @ORM\Table(name="role")
*/
class Role implements RoleInterface
{
/**
* @ORM\Id
* @ORM\Column(name="id", type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @ORM\Column(name="name", type="string", length="255")
*/
protected $name;
/**
* @ORM\Column(name="createdAt", type="datetime", name="created_at")
*/
protected $createdAt;
/**
* @return integer The id.
*/
public function getId()
{
return $this->id;
}
/**
* @return string The name.
*/
public function getName()
{
return $this->name;
}
/**
* @param string $value The name.
*/
public function setName($value)
{
$this->name = $value;
}
/**
* @return DateTime A DateTime object.
*/
public function getCreatedAt()
{
return $this->createdAt;
}
/**
* Constructs a new instance of Role.
*/
public function __construct()
{
$this->createdAt = new \DateTime();
}
/**
* Implementation of getRole for the RoleInterface.
*
* @return string The role.
*/
public function getRole()
{
return $this->getName();
}
}
My SecurityController
<?php
namespace Web20\CMSBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\Security\Core\SecurityContext;
use Web20\CMSBundle\Entity\Category;
class SecurityController extends Controller
{
public function loginAction()
{
if ($this->get('request')->attributes->has(SecurityContext::AUTHENTICATION_ERROR)) {
$error = $this->get('request')->attributes->get(SecurityContext::AUTHENTICATION_ERROR);
} else {
$error = $this->get('request')->getSession()->get(SecurityContext::AUTHENTICATION_ERROR);
}
//$em = $this->getDoctrine()->getEntityManager();
//$salt = $em->getRepository('Web20\CMSBundle\Entity\User')->findOneById(1);
//print_r($salt->getSalt());
return $this->render('Web20CMSBundle:Default:login.html.twig', array(
'last_username' => $this->get('request')->getSession()->get(SecurityContext::LAST_USERNAME),
'error' => $error
));
}
}
My User entity
<?php
namespace Web20\CMSBundle\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\Security\Core\User\UserInterface;
use Doctrine\ORM\Mapping as O开发者_运维技巧RM;
/**
* @ORM\Entity
* @ORM\Table(name="users")
*/
class User implements UserInterface
{
/**
* @ORM\Id
* @ORM\Column(name="id", type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @ORM\Column(name="username", type="string", length="255", unique=true)
*/
private $username;
/**
* @ORM\Column(name="password", type="string", length="255")
*/
private $password;
/**
* @ORM\Column(name="salt", type="string", length="255")
*/
private $salt;
/**
* @ORM\ManyToMany(targetEntity="Role")
* @ORM\JoinTable(name="user_role",
* joinColumns={@ORM\JoinColumn(name="user_id", referencedColumnName="id", onDelete="CASCADE")},
* inverseJoinColumns={@ORM\JoinColumn(name="role_id", referencedColumnName="id")}
* )
* @var ArrayCollection $role
* !IMPORTANTE!: onDelete="cascade" is necessary
*/
private $userRoles;
/**
* @ORM\Column(name="firstName", type="string")
*/
private $firstName;
/**
* @ORM\Column(name="lastName", type="string")
*/
private $lastName;
/**
* @ORM\Column(name="email", type="string")
*/
private $email;
/**
* @return string The username.
*/
public function getUsername()
{
return $this->username;
}
/**
* @param string $value The username.
*/
public function setUsername($value)
{
$this->username = $value;
}
/**
* @param string $value The first name.
*/
public function setFirstName($value)
{
$this->firstName = $value;
}
/**
* @param string $value The last name.
*/
public function setLastName($value)
{
$this->lastName = $value;
}
/**
* @param string $value The email address.
*/
public function setEmail($value)
{
$this->email = $value;
}
/**
* @return string The password.
*/
public function getPassword()
{
return $this->password;
}
/**
* @param string $value The password.
*/
public function setPassword($value)
{
$this->password = $value;
}
/**
* @return string The salt.
*/
public function getSalt()
{
return $this->salt;
}
/**
* @param string $value The salt.
*/
public function setSalt($value)
{
$this->salt = $value;
}
/**
* @return ArrayCollection A Doctrine ArrayCollection
*/
public function getUserRoles()
{
return $this->userRoles;
}
/**
* Constructs a new instance of User
*/
public function __construct()
{
$this->userRoles = new ArrayCollection();
$this->createdAt = new \DateTime();
}
/**
* Erases the user credentials.
*/
public function eraseCredentials()
{
}
/**
* @return array An array of Role objects
*/
public function getRoles()
{
return $this->getUserRoles()->toArray();
}
/**
* Compares this user to another to determine if they are the same.
*
* @param UserInterface $user The user
* @return boolean True if equal, false othwerwise.
*/
public function equals(UserInterface $user)
{
return md5($this->getUsername()) == md5($user->getUsername());
}
}
The important part of login.html.twig looks like that:
<label for="_username">Username:</label>
<input type="text" name="_username" id="username" value="{{ last_username }}"/>
<label for="_password">Password:</label>
<input type="password" name="_password" id="password"/>
while the user is created like this:
$role = new Role();
$role->setName('ROLE_ADMIN');
$role1 = new Role();
$role1->setName('ROLE_CUSTOMER');
$role2 = new Role();
$role2->setName('ROLE_SALESMAN');
$role3 = new Role();
$role3->setName('ROLE_CONTENT_ADMIN');
$manager->persist($role);
$manager->persist($role1);
$manager->persist($role2);
$manager->persist($role3);
$user = new User();
$user->setFirstName('FirstName');
$user->setLastName('LastName');
$user->setEmail('lulz@roflmao.com');
$user->setUsername('admin');
$user->setSalt(md5(time()));
$encoder = new MessageDigestPasswordEncoder('sha512', true, 3);
$password = $encoder->encodePassword('admin', $user->getSalt());
$user->setPassword($password);
$user->getUserRoles()->add($role);
$manager->persist($user);
$manager->flush();
I don't have the time to check all your code but I see two things : 1) Your user 'user' won't be able to login because you gave him a password : 'userpass' although you have set the passwords to be 3 times sha512 encoded and then base64 encoded. You should encode your password and then use the encoded in the settings file. 2) I had a problem with 'encode-as-base64: true' . If you can't login after fixing the first issue then try using 'encode-as-base64: false'. Of course you must provide the password not encoded as base64 this time.
Hope this helps.
精彩评论