问题描述
这是我的原始问题我在身份验证期间试图重新验证用户密码以从旧数据库迁移.
在那里实施有用的答案后.我现在遇到了另一个问题,我没有收到错误(带有以下代码),但是数据库中没有更新密码和盐:
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 ;
}
}
password hreashash.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 ;
}
}
推荐答案
如果要存储PasswordRehash#rehash()作为用户密码的值的结果,请返回新密码的方法:
function rehash($raw) { return parent::encodePassword($raw, null); }
然后,要更新用户,您需要设置新密码并存储更改.
在您的服务中注入学说EntityManager:
club.hub_authenticator: class: AppBundle\Service\HubAuthenticator arguments: ["@security.token_storage" ,"@club.password_rehash", "@doctrine.orm.entity_manager" ]
和您的班级:
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; }
然后使用它:
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); }
但是,我真的不确定您正在实现的逻辑. 我看不到扩展bcryptpasswordencoder的好处.
您应该查看这篇文章显示了一种快速的方法您的用户从旧应用程序到fosuserbundle-cumiant密码的密码仅一次,而不是在每个身份验证上进行.
然后更多地查看如何与服务中的服务一起工作symfony2+.
希望这对您有帮助.
问题描述
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 ; } }
推荐答案
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.