What is preventing passwords being rehashed with the injected Symfony services (FOSUserBundle)

对着背影说爱祢 提交于 2019-12-23 16:27:34

问题


This is a follow up question to my original question where I am trying to rehash user passwords during authentication to migrate from a legacy database.

After implementing the helpful answer there. I have now hit another problem where I receive no error (with the below code) but the passwords and salt are not being updated in the database:

security.yml

security:
    encoders:
        AppBundle\Entity\Member:
        id: club.hub_authenticator

services.yml

services:
    club.hub_authenticator:
        class: AppBundle\Service\HubAuthenticator
        arguments: ["@security.token_storage" ,"@club.password_rehash"]

    club.password_rehash:
        class: AppBundle\Service\PasswordRehash
        arguments: [ "@security.token_storage" ]

HubAuthenticator.php

namespace AppBundle\Service;
use Symfony\Component\Security\Core\Encoder\PasswordEncoderInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;

class HubAuthenticator extends \Symfony\Component\Security\Core\Encoder\BCryptPasswordEncoder implements PasswordEncoderInterface
{
    private $storage ;
    private $passwordRehash ;

    function __construct(TokenStorageInterface $storage, PasswordRehash $passwordRehash, $cost = 13)
    {
        parent::__construct($cost);

        $this->storage=$storage ;
        $this->passwordRehash = $passwordRehash;
    }

    function isPasswordValid($encoded, $raw, $salt)
    {
        // Test for legacy authentication (and conditionally rehash the password in the database)
        if ($this->comparePasswords($encoded, sha1("SaltA".$raw."SaltB"))) {
            $this->passwordRehash->rehash($raw);
            return true ;
        }

        // Test for Bcrypt authentication
        if (parent::isPasswordValid($encoded,$raw,$salt)) return true ;
    }
}

PasswordRehash.php

namespace AppBundle\Service;
use Symfony\Component\Security\Core\Encoder\PasswordEncoderInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;


class PasswordRehash extends \Symfony\Component\Security\Core\Encoder\BCryptPasswordEncoder  implements PasswordEncoderInterface
{
    // private $storage ;

    function __construct(TokenStorageInterface $storage , $cost = 13)
    {
        parent::__construct($cost);
        // $this->storage=$storage ;
    }



    // Customises BCryptPasswordEncoder to use legacy Club SHA method
    function rehash($raw)
    {
        // Commented out as I THINK the $raw is the plainPassword I'm trying to use to reencode the password
        // $user=$this->storage->getToken()->getUser();
        // $token = $this->storage->getToken();

        //Salt left empty as have read this will auto-generate a new one (which is also better practice)
        parent::encodePassword($raw, $salt=null ) ;

        return true ;
    }
}

回答1:


If you want to store the result of PasswordRehash#rehash() as the value of your user's password, make your method returning the new password:

function rehash($raw)
{        
    return parent::encodePassword($raw, null);
}

Then, to update the user, you need to set the new password and store the changes.

Inject the doctrine EntityManager in your service:

club.hub_authenticator:
    class: AppBundle\Service\HubAuthenticator
    arguments: ["@security.token_storage" ,"@club.password_rehash", "@doctrine.orm.entity_manager" ]

And in your class:

use Doctrine\ORM\EntityManager;

function __construct(TokenStorageInterface $storage, PasswordRehash $passwordRehash, EntityManager $em, $cost = 13)
{
    parent::__construct($cost);

    $this->storage = $storage;
    $this->passwordRehash = $passwordRehash;
    $this->em = $em;
}

Then use it:

if (!$token = $this->storage->getToken()) {
    return;
}

if ($this->comparePasswords($encoded, sha1("SaltA".$raw."SaltB"))) {
    // Retrieve the user
    $user = $token->getUser();
    // Change the user password
    $user->setPassword($this->passwordRehash->rehash($raw));
    // Save the changes
    $em->flush($user);
}

But, I'm really not sure about the logic you are implementing. I don't see the benefit of extending the BcryptPasswordEncoder.

You should look at this post that shows a quick way to convert the password of your users from a legacy app to FOSUserBundle-compliant passwords in only one time, rather than do it on each authentication.

Then look more at how to work with services in Symfony2+.
Hope this helps you.



来源:https://stackoverflow.com/questions/36703134/what-is-preventing-passwords-being-rehashed-with-the-injected-symfony-services

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!