fosuserbundle 如何在不提供盐的情况下执行登录操作

How fosuserbundle performs the login action without provided salt

在 symfony 2.8 中我们使用 bcrypt 作为密码编码算法。问题是盐是每次我们进行身份验证时生成的随机值。因此,即使我使用相同的密码,每次也会使用不同的盐对其进行编码。还有我的问题:鉴于编码后的密码总是不同的,它如何与数据库中存储的密码相匹配???或者也许我错过了什么。这是我执行的一个基本示例,密码从未匹配。

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Component\HttpFoundation\Response;
use FOS\UserBundle\FOSUserEvents;
use FOS\UserBundle\Event\GetResponseUserEvent;
use Symfony\Component\HttpFoundation\Request;
  use Primicia\SeguridadBundle\Entity\Usuario as Usuario;

class ServicesController extends Controller
{
    public function loginServiceAction($user,$pass,Request $request){
        $response = new Response();
        $userManager = $this->container->get('fos_user.user_manager');
        $userFos = $userManager->findUserBy(array('username' => $user));
        if($userFos== null)
        {
           $response->setContent(json_encode(array('isUser' => false)));
           return $response;
        }
        $encoder = $this->container->get('security.password_encoder');
        $encoded = $encoder->encodePassword($userFos,$pass);
        echo 'salt'.$userFos->getPlainPassword().'</br>';
        echo ('enc  '.$encoded);
        echo '</br> user'.$userFos->getPassword();

 }
}

如果我们检查 $encoder->encodePassword() 方法,我们会发现:

/**
 * {@inheritdoc}
 */
public function encodePassword(UserInterface $user, $plainPassword)
{
    $encoder = $this->encoderFactory->getEncoder($user);

    return $encoder->encodePassword($plainPassword, $user->getSalt());
}

这里我们看到我们使用用户提供的盐进行编码,但由于我们是 Symfony 2.8 和 bcrypt 算法,因此数据库中没有盐。那么,这里的魔法是怎么发生的呢????

Using the BCrypt Password Encoder所述

A salt for each new password is generated automatically and need not be persisted. Since an encoded password contains the salt used to encode it, persisting the encoded password alone is enough.

事实上,如果您使用 BCrypt 来 User 实体中 UserInterface 的实现所需的 getSalt() 方法可以对您的密码进行编码。

根据OP评论更新:

您可以使用该服务将明文密码与存储的密码进行比较:

$encoderService = $this->container->get('security.password_encoder')

然后是方法isPasswordValid

$match = $encoderService->isPasswordValid($userFosObject, $plainPasswordString)

如果比较匹配则 returns 为真,否则为假。