我正在使用 Symfony 框架编写一个网站,但由于某种原因,登录过程不起作用。
我总是收到消息:Bad credentials
这是我的security.yml
# app/config/security.yml
jms_security_extra:
secure_all_services: false
expressions: true
security:
firewalls:
secured_area:
pattern: ^/
anonymous: ~
form_login:
login_path: /login
check_path: /login_check
access_control:
- { path: ^/admin, roles: ROLE_ADMIN }
providers:
in_memory:
memory:
users:
user: { password: userpass, roles: [ 'ROLE_USER' ] }
contant_manager: { password: manpass, roles: [ 'ROLE_CONTENT_MANAGER' ] }
admin: { password: adminpass, roles: [ 'ROLE_ADMIN' ] }
encoders:
Symfony\Component\Security\Core\User\User: plaintext
我的 User.php 类
<?php
namespace YouMustKnowIt\NewsBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\AdvancedUserInterface;
use Doctrine\Common\Collections\ArrayCollection;
use APY\DataGridBundle\Grid\Mapping as GRID;
/**
* @ORM\Table(name="users")
* @ORM\Entity(repositoryClass="\YouMustKnowIt\NewsBundle\Entity\UserRepository")
*
* @GRID\Source(columns="id, username, email, role.name, isActive")
*/
class User implements AdvancedUserInterface, \Serializable
{
/**
* @ORM\Column(type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*
* @GRID\Column(filterable=false)
*/
private $id;
/**
* @ORM\Column(type="string", length=25, unique=true)
*/
private $username;
/**
* @ORM\Column(type="string", length=32)
*/
private $salt;
/**
* @ORM\Column(type="string", length=100)
*/
private $password;
/**
* @ORM\Column(type="string", length=60, unique=true)
*/
private $email;
/**
* @ORM\ManyToMany(targetEntity="RolesList", inversedBy="users")
*
* @GRID\Column(field="roleslist.role", type="text", filter="select", title="role")
*/
private $role;
/**
* @ORM\OneToMany(targetEntity="NewsCatalog", mappedBy="user")
* @ORM\Column(name="created_news", nullable=true)
*/
private $createdNews;
/**
* @ORM\Column(name="is_active", type="boolean")
*/
private $isActive;
public function __construct()
{
$this->isActive = false;
$this->salt = md5(uniqid(null, true));
$this->role = new \Doctrine\Common\Collections\ArrayCollection();
$this->createdNews = new \Doctrine\Common\Collections\ArrayCollection();
}
public function __toString()
{
return $this->username;
}
public function isAccountNonExpired()
{
return true;
}
public function isAccountNonLocked()
{
return true;
}
public function isCredentialsNonExpired()
{
return true;
}
public function isEnabled()
{
return $this->isActive;
}
/**
* @inheritDoc
*/
public function getRoles()
{
return $this->role->toArray();
}
/**
* @inheritDoc
*/
public function getUsername()
{
return $this->username;
}
/**
* @inheritDoc
*/
public function getSalt()
{
return $this->salt;
}
/**
* @inheritDoc
*/
public function getPassword()
{
return $this->password;
}
/**
* @inheritDoc
*/
public function getEmail()
{
return $this->email;
}
/**
* @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);
}
/**
* 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;
}
/**
* 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;
}
/**
* Add role
*
* @param \YouMustKnowIt\NewsBundle\Entity\RolesList $role
* @return User
*/
public function addRole(\YouMustKnowIt\NewsBundle\Entity\RolesList $role)
{
$this->role[] = $role;
return $this;
}
/**
* Remove role
*
* @param \YouMustKnowIt\NewsBundle\Entity\RolesList $role
*/
public function removeRole(\YouMustKnowIt\NewsBundle\Entity\RolesList $role)
{
$this->role->removeElement($role);
}
/**
* Add createdNews
*
* @param \YouMustKnowIt\NewsBundle\Entity\NewsCatalog $createdNews
* @return User
*/
public function addCreatedNews(\YouMustKnowIt\NewsBundle\Entity\NewsCatalog $createdNews)
{
$this->createdNews[] = $createdNews;
return $this;
}
/**
* Remove createdNews
*
* @param \YouMustKnowIt\NewsBundle\Entity\NewsCatalog $createdNews
*/
public function removeCreatedNews(\YouMustKnowIt\NewsBundle\Entity\NewsCatalog $createdNews)
{
$this->createdNews->removeElement($createdNews);
}
/**
* Get createdNews
*
* @return \Doctrine\Common\Collections\Collection
*/
public function getCreatedNews()
{
return $this->createdNews;
}
/**
* Get role
*
* @return \Doctrine\Common\Collections\Collection
*/
public function getRole()
{
return $this->role;
}
}
我的 UserRepository.php 类
<?php
namespace YouMustKnowIt\NewsBundle\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;
class UserRepository extends EntityRepository implements UserProviderInterface
{
public function loadUserByUsername($username)
{
$q = $this
->createQueryBuilder('u')
->select('u, g')
->leftJoin('u.groups', 'g')
->where('u.username = :username OR u.email = :email')
->setParameter('username', $username)
->setParameter('email', $username)
->getQuery();
try {
$user = $q->getSingleResult();
} catch (NoResultException $e) {
$message = sprintf(
'Unable to find an active admin User object identified by "%s".',
$username
);
throw new UsernameNotFoundException($message, 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());
}
public function findAll()
{
return $this->createQueryBuilder('u');
}
}
安全控制器.php
<?php
namespace YouMustKnowIt\NewsBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\Security\Core\SecurityContext;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Component\HttpFoundation\Request;
use YouMustKnowIt\NewsBundle\Entity\User;
class SecurityController extends Controller
{
/**
* @Route("/login", name="login")
*/
public function loginAction()
{
$request = $this->getRequest();
$session = $request->getSession();
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(
'YouMustKnowItNewsBundle:User:login.html.twig',
array(
'last_username' => $session->get(SecurityContext::LAST_USERNAME),
'error' => $error,
)
);
}
/**
* @Route("/login_check", name="login_check")
*/
public function loginCheckAction()
{
}
/**
* @Route("/logout", name="logout")
*/
public function logoutAction()
{
}
/**
* @Route("/recover_pass", name="recover_pass")
*/
public function recoverPasswordAction(Request $request)
{
$data = array();
$form = $this->createFormBuilder($data)
->add('email', 'email')
->getForm();
if ($request->getMethod() == 'POST') {
$form->bind($request);
if ($form->isValid()) {
$data = $form->getData();
$user = $this->getDoctrine()
->getRepository('YouMustKnowItNewsBundle:User')
->findOneByEmail($data['email']);
if (isset($user)) {
$this->createNewPassword($user);
return $this->redirect($this->generateUrl('homepage'));
} else {
$this->get('session')->getFlashbag()->add(
'error_message',
'The user with such email doesn\'t exist.'
);
}
}
}
return $this->render('YouMustKnowItNewsBundle:Default:recoverPass.html.twig', array(
'form' => $form->createView()
));
}
private function sendEmail(User $user)
{
$message = \Swift_Message::newInstance()
->setSubject('YouMustKnowIt! Password restoration.')
->setFrom('php.gr2@gmail.com')
->setTo($user->getEmail())
->setBody('Your new password: ' . $user->getPassword());
$this->get('mailer')->send($message);
}
private function generatePassword($length = 7)
{
$num = range(0, 9);
$alf = range('a', 'z');
$_alf = range('A', 'Z');
$symbols = array_merge($num, $alf, $_alf);
shuffle($symbols);
$code_array = array_slice($symbols, 0, $length);
$code = implode("", $code_array);
return $code;
}
private function encodePassword(User $user)
{
$factory = $this->get('security.encoder_factory');
$encoder = $factory->getEncoder($user);
$password = $encoder->encodePassword(
$user->getPassword(),
$user->getSalt()
);
return $password;
}
private function createNewPassword(User $user)
{
$password = $this->generatePassword();
$user->setPassword($password);
$this->sendEmail($user);
$encodedPassword = $this->encodePassword($user);
$user->setPassword($encodedPassword);
$em = $this->getDoctrine()->getEntityManager();
$em->persist($user);
$em->flush();
$this->get('session')->getFlashbag()->add(
'success_message',
'On your email the new password was sent.'
);
}
}
最后是 login.html.twig
{% extends '::base.html.twig' %}
{% block body %}
{% if error %}
<div>{{ error.message }}</div>
{% endif %}
<form action="{{ path('login_check') }}" method="post">
<label for="username">Username:</label>
<input type="text" id="username" name="_username" value="{{ last_username }}" />
<label for="password">Password:</label>
<input type="password" id="password" name="_password" />
#<input type="hidden" name="_csrf_token" value="/" />
<input type="submit" name="login" />
</form>
{% endblock %}