1

我已经阅读了有关此问题的所有 SO 帖子,但我仍然找不到我的错误。我正在尝试使用 sha512 让我的登录工作正常。我认为密码编码不正确,因为我在这个网站上检查过。我使用的密码是“asdf”,生成的盐是“fe739a9eafaff0a5b5091d51e1642a34”,存储在我的数据库中的密码是“HzK/fSfJjLQAuAgUhxBzQaPT8cJQ0/05pt5zcYoSM4d7Dxd/WDBiJYXIMmFF70I+”。这是我的问题吗?我根本无法摆脱该死的“坏凭证”这件事。我的代码如下...

安全.yml

security:
    encoders:
        MyBundle\MainBundle\Entity\SystemUser:
            algorithm: sha512
            iterations: 1

    role_hierarchy:
        ROLE_STUDENT:
        ROLE_GUARDIAN:
        ROLE_TEACHER:
        ROLE_SCHOOL_ADMIN:  ROLE_STUDENT, ROLE_GUARDIAN
        ROLE_ADMIN:         ROLE_SCHOOL_ADMIN, ROLE_STUDENT, ROLE_GUARDIAN
        ROLE_SUPER_ADMIN:   [ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]

    providers:
        users:
            entity: { class: MyBundleMainBundle:SystemUser }

    firewalls:
        secured_area:
            pattern: ^/
            anonymous: ~
            form_login:
                login_path: login
                check_path: login_check
                csrf_provider: form.csrf_provider
                csrf_parameter: _csrf_token
                always_use_default_target_path: true
                default_target_path: /dashboard
            logout: true
            anonymous: true

然后,我的SystemUser类(抱歉这么长,这里只想说的比较全面)

<?php

namespace MyBundle\MainBundle\Entity;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\AdvancedUserInterface;
use Symfony\Component\Validator\Constraints\Collection;

/**
 * SystemUser
 *
 * @ORM\Table()
 * @ORM\Entity(repositoryClass="MyBundle\MainBundle\Entity\Repository\SystemUserRepository")
 * @ORM\InheritanceType("JOINED")
 * @ORM\DiscriminatorColumn(name="discr", type="integer")
 * @ORM\DiscriminatorMap({"0" = "SystemUser", "1" = "SchoolAdmin", "2" = "Teacher", "3" = "Student", "4" = "Guardian"})
 */
class SystemUser implements AdvancedUserInterface, \Serializable {
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @var string
     *
     * @ORM\Column(type="string", length=50)
     */
    protected $username;

    /**
     * @var string
     *
     * @ORM\Column(type="string", length=255)
     */
    protected $email;

    /**
     * @var string
     *
     * @ORM\Column(type="string", length=32)
     */
    protected $salt;

    /**
     * @var string
     *
     * @ORM\Column(type="string", length=64)
     */
    protected $password;

    /**
     * @var bool
     *
     * @ORM\Column(type="boolean", name="is_active")
     */
    protected $isActive;

    /**
     * @var string
     * @ORM\Column(name="birth_date", type="date")
     */
    protected $birthDate;

    /**
     * @var string
     * @ORM\Column(name="cellphone", type="string", length=10)
     */
    protected $cellphone;

    /**
     * @var ArrayCollection
     * @ORM\ManyToMany(targetEntity="Role", inversedBy="users")
     */
    protected $roles;

    /**
     * @var integer
     * Use this to map to the discr column...
     */
    protected $discr;

    /**
     *
     *
     *
     *
     * Begin methods
     *
     *
     *
     */


    public function __construct() {
        $this->isActive = true;
        $this->salt = md5(uniqid(null, true));
        $this->roles = new ArrayCollection();
    }

    /**
     * Get id
     *
     * @return integer 
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set birthDate
     *
     * @param \DateTime $birthDate
     * @return SystemUser
     */
    public function setBirthDate($birthDate)
    {
        $this->birthDate = $birthDate;

        return $this;
    }

    /**
     * Get birthDate
     *
     * @return \DateTime 
     */
    public function getBirthDate()
    {
        return $this->birthDate;
    }

    /**
     * Set cellphone
     *
     * @param string $cellphone
     * @return SystemUser
     */
    public function setCellphone($cellphone)
    {
        $this->cellphone = $cellphone;

        return $this;
    }

    /**
     * Get cellphone
     *
     * @return string 
     */
    public function getCellphone()
    {
        return $this->cellphone;
    }

    /**
     * (PHP 5 &gt;= 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,
        ));
    }

    /**
     * (PHP 5 &gt;= 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) = unserialize($serialized);
    }

    /**
     * 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 $this->roles;
    }

    /**
     * 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;
    }

    /**
     * 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()
    {
        return $this->salt;
    }

    /**
     * Returns the username used to authenticate the user.
     *
     * @return string The username
     */
    public function getUsername()
    {
        return $this->username;
    }

    /**
     * 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.
    }

    /**
     * Checks whether the user's account has expired.
     *
     * Internally, if this method returns false, the authentication system
     * will throw an AccountExpiredException and prevent login.
     *
     * @return Boolean true if the user's account is non expired, false otherwise
     *
     * @see AccountExpiredException
     */
    public function isAccountNonExpired()
    {
        return true;
    }

    /**
     * Checks whether the user is locked.
     *
     * Internally, if this method returns false, the authentication system
     * will throw a LockedException and prevent login.
     *
     * @return Boolean true if the user is not locked, false otherwise
     *
     * @see LockedException
     */
    public function isAccountNonLocked()
    {
        return true;
    }

    /**
     * Checks whether the user's credentials (password) has expired.
     *
     * Internally, if this method returns false, the authentication system
     * will throw a CredentialsExpiredException and prevent login.
     *
     * @return Boolean true if the user's credentials are non expired, false otherwise
     *
     * @see CredentialsExpiredException
     */
    public function isCredentialsNonExpired()
    {
        return true;
    }

    /**
     * Checks whether the user is enabled.
     *
     * Internally, if this method returns false, the authentication system
     * will throw a DisabledException and prevent login.
     *
     * @return Boolean true if the user is enabled, false otherwise
     *
     * @see DisabledException
     */
    public function isEnabled()
    {
        return $this->isActive;
    }

    /**
     * Set username
     *
     * @param string $username
     * @return SystemUser
     */
    public function setUsername($username)
    {
        $this->username = $username;

        return $this;
    }

    /**
     * Set email
     *
     * @param string $email
     * @return SystemUser
     */
    public function setEmail($email)
    {
        $this->email = $email;

        return $this;
    }

    /**
     * Get email
     *
     * @return string 
     */
    public function getEmail()
    {
        return $this->email;
    }

    /**
     * Set salt
     *
     * @param string $salt
     * @return SystemUser
     */
    public function setSalt($salt)
    {
        $this->salt = $salt;

        return $this;
    }

    /**
     * Set password
     *
     * @param string $password
     * @return SystemUser
     */
    public function setPassword($password)
    {
        $this->password = $password;

        return $this;
    }

    /**
     * Set isActive
     *
     * @param boolean $isActive
     * @return SystemUser
     */
    public function setIsActive($isActive)
    {
        $this->isActive = $isActive;

        return $this;
    }

    /**
     * Get isActive
     *
     * @return boolean 
     */
    public function getIsActive()
    {
        return $this->isActive;
    }

    /**
     * Add roles
     *
     * @param \MyBundle\MainBundle\Entity\Role $role
     * @return SystemUser
     */
    public function addRole(\MyBundle\MainBundle\Entity\Role $role)
    {
        $this->roles[] = $role;

        return $this;
    }

    public function removeRole(\MyBundle\MainBundle\Entity\Role $role) {
        $this->roles->removeElement($role);

    }

    /**
     * Get discr
     *
     * @return int
     */
    public function getDiscr() {
        return $this->discr;
    }

    /**
     * Set discr
     *
     * @param $discr
     * @return \MyBundle\MainBundle\Entity\SystemUser
     */
    public function setDiscr($discr) {
        $this->discr = $discr;

        return $this;
    }
}

我的系统用户存储库

class SystemUserRepository extends EntityRepository implements UserProviderInterface
{

    public function loadUserByUsername($username)
    {
        $query = $this->createQueryBuilder('su')
            ->select('su, sr') //SystemUser, SystemRoles
            ->leftJoin('su.roles', 'sr')
            ->where('su.username = :username OR su.email = :email')
            ->setParameter('username', $username)
            ->setParameter('email', $username)
            ->getQuery();

        try {
            $user = $query->getSingleResult();
        } catch (NoResultException $e) {
            $message = 'Unable to find user \'' . $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(
                'Instances of \'' . $class . '\' are not supported'
            );
        }

        return $this->find($user->getId());
    }

    public function supportsClass($class)
    {
        return $this->getEntityName() === $class
                || is_subclass_of($class, $this->getEntityName());
    }
}

最后是我的登录

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(
            'MyBundleMainBundle:Security:login.html.twig',
            array(
                'last_username' => $session->get(SecurityContext::LAST_USERNAME),
                'error' => $error,
                'csrf_token' => $this->container->get('form.csrf_provider')->generateCsrfToken('authenticate'),
            )
        );
    }

哦,如果有任何后果,我的注册控制器。

public function createUserAction(Request $request) {
        $entityManager = $this->getDoctrine()->getManager();
        $form = $this->createForm('user_registration', new Registration());
        $form->handleRequest($request);

        if ($form->isValid()) {
            $registration = $form->getData();

            //Handle encoding here...
            $encoderFactory = $this->get('security.encoder_factory');
            $encoder = $encoderFactory->getEncoder($registration->getUser());
            $password = $encoder->encodePassword($registration->getUser()->getPassword(), $registration->getUser()->getSalt());
            $registration->getUser()->setPassword($password);

            $entityManager->persist($registration->getUser());
            $entityManager->flush();

            return $this->redirect($this->generateUrl('dashboard_homepage'));
        }

        return $this->render(
            'MyBundleMainBundle:Security:registration.html.twig',
            array(
                'form' => $form->createView()
            )
        );
    }

抱歉发了这么长的帖子,希望有人可以在这里帮助我!非常感谢!

4

1 回答 1

3

在 SystemUser 类中更改以下代码:

/**
* @var string
*
* @ORM\Column(type="string", length=64)
*/
protected $password;

/**
* @var string
*
* @ORM\Column(type="string", length=255)
*/
protected $password;

在遵循 symfony.com 上的指南后,我偶然发现了与您相同的问题。通过比较哈希密码在持久化到数据库之前和之后的结果,我可以看到哈希密码的长度为 88 个字符,因此在持久化到数据库后被截断为 64 个字符。

FOSUserBundle 在他们的密码字段上也使用了 255 的长度,所以我想这是一个合法的改变。

我猜你已经解决了这个问题,因为你刚刚发布了它,但我想我会帮助其他人,就像我一样,来到这里遇到同样的问题。

于 2014-01-03T14:15:30.513 回答