1

この問題に関する文字通りすべての SO 投稿を確認しましたが、まだバグが見つかりません。sha512 を使用してログインを機能させようとしています。このサイトで確認したところ、パスワードが正しくエンコードされていないと思います。使用したパスワードは「asdf」、生成されるソルトは「fe739a9eafaff0a5b5091d51e1642a34」、DB に保存されているパスワードは「HzK/fSfJjLQAuAgUhxBzQaPT8cJQ0/05pt5zcYoSM4d7Dxd/WDBiJYXIMmFF70I+」です。これは私の問題ですか?いまいましい「Bad Credentials」の問題を乗り越えることはできません。私のコードは以下です...

security.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;
    }
}

私の SystemUserRepository

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 に答える