0

我正在使用 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 %}
4

1 回答 1

0

如果您使用的是映射到数据库的实体,那么您Provider:缺少正确的映射。

providers:
    users:
        entity: { class: YouMustKnowItNewsBundle:User, property: username }
于 2013-05-23T09:02:51.057 回答