Php 哈希密码和createQueryBuilder()

Php 哈希密码和createQueryBuilder(),php,doctrine-orm,symfony,Php,Doctrine Orm,Symfony,这是我设置密码的方式: $member->setPassword(password_hash($_POST['pw1'], PASSWORD_DEFAULT)); 要检查密码是否正确,我只需使用以下代码: if(password_verify($password, $hashed_pw)) { // $hashed_pw is not set, since this is just an example // Do something here } 到目前为止一切都很好 问题

这是我设置密码的方式:

$member->setPassword(password_hash($_POST['pw1'], PASSWORD_DEFAULT));
要检查密码是否正确,我只需使用以下代码:

if(password_verify($password, $hashed_pw)) { // $hashed_pw is not set, since this is just an example
    // Do something here
}
到目前为止一切都很好

问题

我正在使用此方法生成查询:

private function getData($username, $password) {
    // Getting the data
    $query = $this->getDoctrine()->getRepository('AppBundle:Members')
        ->createQueryBuilder('t')
        ->where('t.email = :email')
        ->andWhere('t.password = :password')
        ->setParameter('email', $username)
        ->setParameter('password', $password)
        ->getQuery();
    $result = $query->getResult();

    // Get the name
    $name = $result[0]->getName();

    // Check if query exists
    $result = ($result) ? $name : false;
    return $result;
}
如果密码没有散列,一切都会正常工作。嗯,在我的情况下,密码是散列的,我不知道如何才能通过这个


我完全糊涂了,任何帮助都将不胜感激

没关系,我只回答我自己的问题。我只需要创建另一个查询:

private function getData($username, $password) {

    // Get the PW
    $query_pw = $this->getDoctrine()->getRepository('AppBundle:Members')
        ->createQueryBuilder('m')
        ->where('m.email = :email')
        ->setParameter('email', $username)
        ->getQuery();
    $result_pw = $query_pw->getResult();

    if ($result_pw) {
        $hashed_pw = $result_pw[0]->getPassword();
    }
    else {
        $hashed_pw = false;
    }

    // Getting the data
    $query = $this->getDoctrine()->getRepository('AppBundle:Members')
        ->createQueryBuilder('t')
        ->where('t.email = :email')
        ->andWhere('t.password = :password')
        ->setParameter('email', $username)
        ->setParameter('password', $hashed_pw)
        ->getQuery();
    $result = $query->getResult();

    // Verify the password
    if(password_verify($password, $hashed_pw)) {
        // Get the name
        $name = $result[0]->getName();
    }
    else {
        $name = false;
    }

    // Check if query exists
    $result = ($result) ? $name : false;
    return $result;
}
以下是我的答案:

private function verifyUser($username, $password) {
    $em = $this->getDoctrine()->getManager();
    $qb = $em->createQueryBuilder();
    $qb->select('m')
        ->from('AppBundle:Members', 'm')
        ->where('m.email = :email')
        ->andWhere('m.password = :password')
        ->setParameter('email', $username)
        ->setParameter('password', $password)
    ;
    $member = $qb->getQuery()->setMaxResults(1)->getOneOrNullResult();

    if( $member == null ) {
        $result = null;
    }
    else{
        $result = $member->getName();
    }

    return $result;
}
说明:将函数重命名为
verifyUser
,因为它就是这样做的。正如您将看到的,我已经编写了代码,这样当开发人员阅读它时,它应该是有意义的,并且如果您将来必须更改代码,它将更易于支持

我获取EntityManager并创建一个QueryBuilder,然后创建一个设置电子邮件和密码的查询。请注意,我调用了
getOneOrNullResult
,这很重要。如果没有得到结果(null),则传入的密码与存储的密码不匹配,并且这不是用户

我还将
setMaxResults
设置为1,这应该只返回1个结果(如果匹配),因为您应该只有一个用户使用此密码(希望您的设计就是这样-如果不匹配,您需要重新考虑设计)

然后我检查查看
$member
,如果不匹配则为一个成员或null,并将
$result
分别设置为返回

我使用
null
作为返回值,而不是
false
,因为
false
是一个
boolean
,在这种情况下,返回
null
是更好的设计

希望这一切都有意义


编辑#2-合并密码哈希

private function verifyUser($username, $password) {
    $em = $this->getDoctrine()->getManager();
    $qb = $em->createQueryBuilder();
    $qb->select('m')
        ->from('AppBundle:Members', 'm')
        ->where('m.email = :email')
        ->setParameter('email', $username)
    ;
    $member = $qb->getQuery()->setMaxResults(1)->getOneOrNullResult();

     if( password_verify($password, $member->getPasswordHash()) ){
        $result = $member->getName();
    }
    else{
        $result = null;
    }

    return $result;
}

上述方法假定您在成员实体中存储密码散列,然后使用函数
getPasswordHash()

获得密码散列,建议您投票关闭@Cerad,因为它是一篇写得非常糟糕的文章,也是写得很差的代码。@AlvinBunk如果所有写得很差的文章/代码都被关闭了,那么剩下的就不多了。我很想找出这两个问题背后的原因。很好@Cerad。我也回答了很多类似的帖子。让我们拭目以待,看看您是否得到任何响应@AlvinBunk第一个查询返回我需要的哈希密码,因此我可以在第二个查询中使用该值来获取我需要的其余数据。现在我从数据库中获得了密码(参数中给出)和散列密码,我可以使用函数
password\u verify()
。我很确定,您只需一个查询就可以完成同样的操作,但由于我对Symfony非常陌生,而且这是我的第一个学习项目,所以我不知道有什么更好的方法来解决这个问题。如果您有更好的解决方案,请随时回答,我会将其标记为已解决。@Cerad,您得到了响应!谢谢你回复雷扎。看看我的答案。我觉得更好,但你可以决定。祝您有个美好的一天!在使用Symfony时,是否考虑过使用框架提供的工具?非常感谢您花时间发布此答案。你的代码看起来肯定比我的代码干净得多,但老实说,如果你把你的答案和我的答案进行比较,我不太确定我们是否都得到了相同的结果。请注意,
password\u verify()
不是我自己的功能。这是一个PHP现有函数(),基本上是我的问题所在。是的,我确实知道这个函数,但您在代码中没有正确使用它,因此我的答案是。需要在
verifyUser
函数之外调用它,然后如果它匹配,则传入
$password
。这意味着我将有两个函数?第一个是
verifyUser()
,它将返回
$member->getName()
null
,第二个可能被称为
getPassword()
,它将只返回哈希密码。然后我可以在这两个函数之外使用
password\u verify()
,对吗?如果是这样,我仍然需要两个查询,但不是在同一个函数中。还是我错了?顺便问一下,您是否在
成员
实体中存储哈希?如果是这样,也许还有更好的方法来处理这个问题。如果有,请告诉我是否有
getHash()
或类似的方法。我添加了一个EDIT#2,应该可以解决这个问题。确保您没有将密码存储在clear中的任何位置。