我正在尝试根据数据库验证用户。它可以很好地用于明文密码编码。但是当我使用bccrypt加密密码时,它会给出"坏凭据"。
这是我的安全。yml
security:
firewalls:
secured_area:
pattern: ^/
anonymous: ~
form_login:
login_path: /login
check_path: /login_check
logout:
path: /logout
target: /
role_hierarchy:
ROLE_ADMIN: ROLE_USER
access_control:
- { path: ^/admin, roles: ROLE_USER }
providers:
chain_provider:
chain:
providers: [in_memory, user_db]
in_memory:
memory:
users:
foo: { password: test , roles: 'ROLE_USER' }
user_db:
entity: { class: versionR'userBundle'Entity'User, property: username }
encoders:
versionR'userBundle'Entity'User:
algorithm: bcrypt
cost: 5
Symfony'Component'Security'Core'User'User: plaintext
实体类
<?php
// src/Acme/UserBundle/Entity/User.php
namespace versionR'userBundle'Entity;
use Doctrine'ORM'Mapping as ORM;
use Symfony'Component'Security'Core'User'UserInterface;
/**
* Acme'UserBundle'Entity'User
*
* @ORM'Table(name="acme_users")
* @ORM'Entity(repositoryClass="Acme'UserBundle'Entity'UserRepository")
*/
class User implements UserInterface, 'Serializable
{
/**
* @ORM'Column(type="integer")
* @ORM'Id
* @ORM'GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @ORM'Column(type="string", length=25, unique=true)
*/
private $username;
/**
* @ORM'Column(type="string", length=64)
*/
private $password;
/**
* @ORM'Column(type="string", length=60, unique=true)
*/
private $email;
/**
* @ORM'Column(name="is_active", type="boolean")
*/
private $isActive;
/**
* @ORM'Column(name="address", type="string")
*/
private $address;
public function __construct()
{
$this->isActive = true;
// may not be needed, see section on salt below
// $this->salt = md5(uniqid(null, true));
}
/**
* @inheritDoc
*/
public function getUsername()
{
return $this->username;
}
/**
* @inheritDoc
*/
public function getSalt()
{
// you *may* need a real salt depending on your encoder
// see section on salt below
return null;
}
/**
* @inheritDoc
*/
public function getPassword()
{
return $this->password;
}
/**
* @inheritDoc
*/
public function getRoles()
{
return array('ROLE_USER');
}
/**
* @inheritDoc
*/
public function eraseCredentials()
{
}
/**
* @see 'Serializable::serialize()
*/
public function serialize()
{
return serialize(array(
$this->id,
$this->username,
$this->password,
// see section on salt below
// $this->salt,
));
}
/**
* @see 'Serializable::unserialize()
*/
public function unserialize($serialized)
{
list (
$this->id,
$this->username,
$this->password,
// see section on salt below
// $this->salt
) = unserialize($serialized);
}
/**
* Set username
*
* @param string $username
* @return User
*/
public function setUsername($username)
{
$this->username = $username;
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 address
*
* @param string $address
* @return User
*/
public function setAddress($address)
{
$this->address = $address;
return $this;
}
/**
* Get address
*
* @return string
*/
public function getAddress()
{
return $this->address;
}
/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->id;
}
}
和用户存储库类
<?php
namespace versionR'userBundle'Entity;
use Doctrine'ORM'EntityRepository;
use Symfony'Component'Security'Core'User'UserInterface;
use Symfony'Component'Security'Core'User'UserProviderInterface;
/**
* UserRepository
*
* This class was generated by the Doctrine ORM. Add your own custom
* repository methods below.
*/
class UserRepository extends EntityRepository implements UserProviderInterface
{
/**
* @param string $username
* @return 'versionR'userBundle'Entity'User
*/
public function loadUserByUsername($username)
{
return $this->findOneBy(array('username' => $username));
}
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 versionR'userBundle'Command;
use Symfony'Bundle'FrameworkBundle'Command'ContainerAwareCommand;
use Symfony'Component'Console'Input'InputArgument;
use Symfony'Component'Console'Input'InputInterface;
use Symfony'Component'Console'Input'InputOption;
use Symfony'Component'Console'Output'OutputInterface;
use versionR'userBundle'Entity'User;
class userCommand extends ContainerAwareCommand
{
protected function configure()
{
$this
->setName('versionR:users')
->setDescription('Add Jobeet users')
->addArgument('username', InputArgument::REQUIRED, 'The username')
->addArgument('password', InputArgument::REQUIRED, 'The password')
->addArgument('email', InputArgument::REQUIRED, 'The email')
->addArgument('address', InputArgument::REQUIRED, 'The address')
;
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$username = $input->getArgument('username');
$password = $input->getArgument('password');
$email = $input->getArgument('email');
$address = $input->getArgument('address');
$em = $this->getContainer()->get('doctrine')->getManager();
$user = new User();
$user->setUsername($username);
// encode the password
$factory = $this->getContainer()->get('security.encoder_factory');
$encoder = $factory->getEncoder($user);
$encodedPassword = $encoder->encodePassword($password, $user->getSalt());
$user->setPassword($encodedPassword);
$user->setEmail($email);
$user->setAddress($address);
$em->persist($user);
$em->flush();
$output->writeln(sprintf('Added %s user with password %s', $username, $password));
}
}
谁能解释一下为什么这不起作用?谢谢。
既然代码是正确的。问题是在数据库中,要使用加密,在数据库密码字段中应该有足够的空间。根据这个SO回答密码字段应该是CHAR(60)
或BINARY(60)
。如果小于这个长度,那么加密字符串的一半将被保存,结果是错误的凭据。