同福

做个用户管理系统(13)——用户模块user之安全问题功能的实现【20201129】

介绍

介绍

今天我们和福哥一起来好好设计一下安全问题功能,安全问题用来识别账号的安全保护身份。用户在指定若干问题里面挑出三个问题,并提供这三个问题的自己的答案。在验证安全保护身份的时候,用户需要答出这三个问题的答案,且答案要一字不差。这种验证的安全系数是非常高的,即便是和用户本人非常熟悉的人也很难得出三个问题的正确答案。

设置安全问题

代码

/**
 * note:
 *   1 - user is not exists
 *   2 - exception
 *
 * @param int $userID
 * @param int $q1
 * @param string $a1
 * @param int $q2
 * @param string $a2
 * @param int $q3
 * @param string $a3
 * @return int
 */
public function setSecurityQuestions(int $userID, int $q1, string $a1, int $q2, string $a2, int $q3, string $a3):int {
    $tfdo = $this->tfphp->getDatabase()->getTFDO();
    $userInfo = $tfdo->fetchOne("select * from user where userID = @int", $userID);
    if($userInfo == null){

        return 1;
    }

    $sqInfo = $tfdo->fetchOne("select * from user_security_questions where userID = @int", $userID);
    if($sqInfo == null){
        $ret = $tfdo->insert("user_security_questions", array(
            'userID'=>$userID,
            'q1'=>$q1,
            'a1'=>$a1,
            'q2'=>$q2,
            'a2'=>$a2,
            'q3'=>$q3,
            'a3'=>$a3,
        ), array(
            'userID'=>"int",
            'q1'=>"int",
            'q2'=>"int",
            'q3'=>"int",
        ));
    }
    else{
        $ret = $tfdo->update("user_security_questions", array(
            'q1'=>$q1,
            'a1'=>$a1,
            'q2'=>$q2,
            'a2'=>$a2,
            'q3'=>$q3,
            'a3'=>$a3,
        ), array(
            'q1'=>"int",
            'q2'=>"int",
            'q3'=>"int",
        ), "userID = @int", $userID);
    }
    if(!$ret){

        return 2;
    }

    return 0;
}

获取安全问题

代码

/**
 * @param int $userID
 * @return array|null
 */
public function getSecurityQuestions(int $userID):?array {
    $tfdo = $this->tfphp->getDatabase()->getTFDO();

    return $tfdo->fetchOne("select * from user_security_questions where userID = @int", $userID);
}

验证安全问题

代码

/**
 * note:
 *   1 - security questions is not set
 *   2 - answer is wrong
 *   3 - question is invalid
 *
 * @param int $userID
 * @param int $q1
 * @param string $a1
 * @param int $q2
 * @param string $a2
 * @param int $q3
 * @param string $a3
 * @return bool
 */
public function verifySecurityQuestions(int $userID, int $q1, string $a1, int $q2, string $a2, int $q3, string $a3):bool {
    $tfdo = $this->tfphp->getDatabase()->getTFDO();

    $sqInfo = $tfdo->fetchOne("select * from user_security_questions where userID = @int", $userID);
    if($sqInfo == null){

        return 1;
    }

    $userSecurityQuestionInfo = array(
        array('q'=>$sqInfo['q1'], 'a'=>$sqInfo['a1']),
        array('q'=>$sqInfo['q2'], 'a'=>$sqInfo['a2']),
        array('q'=>$sqInfo['q3'], 'a'=>$sqInfo['a3']),
    );
    $verifySecurityQuestionInfo = array(
        array('q'=>$q1, 'a'=>$a1),
        array('q'=>$q2, 'a'=>$a2),
        array('q'=>$q3, 'a'=>$a3),
    );
    foreach ($verifySecurityQuestionInfo as $key => $item){
        $passed = false;
        foreach($userSecurityQuestionInfo as $key2 => $item2){
            if($item['q'] == $item2['q']){
                if($item['a'] != $item2['a']){

                    return  2;
                }
                else{
                    $passed = true;
                    unset($userSecurityQuestionInfo[$key2]);
                    break;
                }
            }
        }
        if(!$passed){

            return 3;
        }
    }

    return 0;
}

讲解

设置安全问题

首先我们要检查当前用户$userID是不是存在的,不存在就没必要继续了。

接着我们要判断当前用户是不是有设置过安全问题,如果有就更新,没有就写入。

三个问题和答案对应三组六个字段,名字不要对应错了。

获取安全问题

直接判断当前用户是不是有设置过安全问题即可,没有这个用户或者没有设置过安全问题都一样。

验证安全问题

首先我们要检查当前用户$userID是不是存在的,不存在就没必要继续了。

取出数据库里的安全问题和答案后,循环和验证的问题和答案逐一判断,通过一组删除一组,不通过就报错。

这里面需要一个小技巧,就是把三组问题和答案放入数组里,数据库里的数据一组,验证数据一组,双重循环进行比较。

总结

今天童鞋们和福哥一起把安全问题的功能的逻辑部分全部都实现了,安全问题将成为用户忘记密码时候作为重置密码的方式之一。

下一课我们将实现个人资料修改的功能,敬请期待~~