Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/271.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PHP中的密码恢复过期时间_Php_Password Recovery - Fatal编程技术网

PHP中的密码恢复过期时间

PHP中的密码恢复过期时间,php,password-recovery,Php,Password Recovery,我正在为我正在开发的网站编写一个简单的密码恢复功能,我想知道过期时间 说到这里,我想为我要发送的重置密码链接添加大约48小时的过期时间。我是否必须创建一个新列来存储当前时间,并在稍后检查它是否仍然有效,或者是否有更简单的方法 这是我目前的代码: public function forgotPass($email) { $bd = new Bd(); $conn = $bd->connect(); $stt = $conn->prepare("SELECT *

我正在为我正在开发的网站编写一个简单的密码恢复功能,我想知道过期时间

说到这里,我想为我要发送的重置密码链接添加大约48小时的过期时间。我是否必须创建一个新列来存储当前时间,并在稍后检查它是否仍然有效,或者是否有更简单的方法

这是我目前的代码:

public function forgotPass($email) {
    $bd = new Bd();
    $conn = $bd->connect();
    $stt = $conn->prepare("SELECT * FROM Users where email=?");
    $stt-> bind_param("s",$email);
    $stt-> execute();
    $result = $stt->get_result();
    if (mysqli_num_rows($result) == 1) {
        $stt = $conn->prepare("INSERT INTO Users(recovery) VALUES(?)");
        $recovery = $this->randHash(8);

        if (!$recovery)
            return false;

        $stt-> bind_param("s",$recovery);
        $stt-> execute();
    }
}
这是我的
randHash
代码:

private static function randHash($lenght) {
    if (!filter_var($lenght, FILTER_VALIDATE_INT)) {
        return false;
    }   
    $allowed = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    $max = strlen($allowed) - 1;
    for ($i=1;$i<=$lenght;$i++) {
        $hash .= $allowed[mt_rand(0, $max)];
    }
    return $hash;
}
私有静态函数randHash($lenght){
如果(!filter\u var($lenght,filter\u VALIDATE\u INT)){
返回false;
}   
$allowed=“0123456789abcdefghijklmnopqrstuvxyzabcdefghijklmnopqrstuvxyz”;
$max=strlen($allowed)-1;

对于($i=1;$i只需将过期时间与重置令牌一起保存在数据库中,当时间过期时,不再接受重置令牌。这是迄今为止最简单、最安全的方法


另一种方法是创建重置散列,附加时间,并使用密钥加密。在检查散列时解密并检查时间戳。但是,如果密钥泄漏,此方法变得像将其以纯文本形式放入URL一样弱。

将当前日期存储在数据库中是一种方法。然后,您可以轻松地检查如果休息时间少于48小时,另一种方法是在电子邮件中加入时间

public function forgotPass($email) {
    $bd = new Bd();
    $conn = $bd->connect();
    $stt = $conn->prepare("SELECT * FROM Users where email=?");
    $stt-> bind_param("s",$email);
    $stt-> execute();
    $result = $stt->get_result();
    if (mysqli_num_rows($result) == 1) {
        $hash1 = md5(microtime().$email.'xx'); //create a unique number for email
        $ctime = time();
        $hash2 = md5($hash1.$ctime); //create a unique hash based on hash1 and time

        $stt = $conn->prepare("INSERT INTO Users(recovery) VALUES(?)");
        $recovery = $hash2;

        if (!$recovery)
            return false;

        $stt-> bind_param("s",$recovery);
        $stt-> execute();

        //send email with link
        // http://www.example.com/resetpass.php?hash=$hash1&time=$ctime
    }
}

//and then in resetpass.php
//NEEDS CHECKS FOR VALID QUERYVALUES

if (time()-$_GET['time'] <= 48 * 60 * 60)  {
  $checkhash = md5($_GET['hash'].$_GET['time']);
  //check database for hash
}
放弃通行证的公共功能($email){
$bd=新bd();
$conn=$bd->connect();
$stt=$conn->prepare(“从电子邮件=?”的用户中选择*”;
$stt->bind_参数(“s”,$email);
$stt->execute();
$result=$stt->get_result();
if(mysqli_num_rows($result)==1){
$hash1=md5(microtime().$email.xx');//为电子邮件创建一个唯一的号码
$ctime=时间();
$hash2=md5($hash1.$ctime);//基于hash1和时间创建唯一的哈希
$stt=$conn->prepare(“插入用户(恢复)值(?);
$recovery=$hash2;
如果(!$recovery)
返回false;
$stt->bind_参数(“s”,$recovery);
$stt->execute();
//发送带有链接的电子邮件
// http://www.example.com/resetpass.php?hash=$hash1&time=$ctime
}
}
//然后在resetpass.php中
//需要检查有效的查询值
if(time()-$\u GET['time']编辑:我今天早上收到一封关于这个答案的电子邮件,询问我答案的哈希部分是否只是为了制作一个真正唯一的ID。以下是我的回答:

我仔细阅读并重新阅读了关于堆栈溢出的问题。该代码不仅用于生成真正唯一的ID(尽管没有冲突很重要)。它还使其他人很难编写自己的密码恢复链接来访问用户帐户

通过创建一个包含用户名和电子邮件的散列(并且不散列整个代码),我们可以对用户的身份进行额外的验证。也就是说,仅仅拥有链接是不够的;还需要一个有效的用户名和电子邮件地址组合来重置密码

在用户名、当前时间和电子邮件前面加上字符串,基本上是为了击败rainbow表。现在回想起来,最好分别用base64_编码($row['username'])和base64_编码($email)替换“”salt


我建议创建两列:recovery和recovery\u expiry。recovery\u expiry在链接过期时有效,recovery保留必须比较的哈希值。它由用户名、当前时间附加的salt和用户的当前电子邮件地址组成

function forgotPass($email)
{
    $currTime = time();
    $expiryTime = 60 * 60 * 24 * 2; // Two days

    $bd = new Bd();
    $conn = $bd->connect();
    $stt = $conn->prepare("SELECT * FROM Users where email=?");
    $stt->bind_param("s", $email);
    $stt->execute();
    $result = $stt->get_result();
    if (mysqli_num_rows($result) == 1)
    {
        $row = mysqli_fetch_array();
        $stt = $conn->prepare("INSERT INTO Users(recovery, recovery_expiry)"
               . " VALUES(?,?)");
        $hash = hash("sha256", " " . $row['username'])
                . hash("sha256", "vivid" . $currTime)
                . hash("sha256", " " . $email);

        $stt->bind_param("s", $hash);
        $stt->bind_param("i", $currTime + $expiryTime);
        $stt->execute();
    }
    else
    {
        // Return that the given email address did not match any records
    }
    // Here would be the logic to send the forgotten password link to the user
}

function checkHash($hash)
{
    $row = null;
    $currTime = time();
    $bd = new Bd();
    $conn = $bd->connect();
    $stt = $conn->prepare("SELECT * FROM Users WHERE recovery=? AND recovery_expiry < $currTime");
    $stt->bind_param("s", $hash);
    $stt->execute();
    $result = $stt->get_result();
    if (mysqli_num_rows($result) == 1)
    {
        $row = mysqli_fetch_array();
    }
    return $row;
}
放弃通行证功能($email)
{
$currTime=time();
$expiryTime=60*60*24*2;//两天
$bd=新bd();
$conn=$bd->connect();
$stt=$conn->prepare(“从电子邮件=?”的用户中选择*”;
$stt->bind_参数(“s”,$email);
$stt->execute();
$result=$stt->get_result();
if(mysqli_num_rows($result)==1)
{
$row=mysqli_fetch_array();
$stt=$conn->prepare(“插入到用户中(恢复、恢复和到期)”
“价值(?,)”;
$hash=hash(“sha256”,即“.$row['username']))
.hash(“sha256”,“生动”。$currTime)
.hash(“sha256”和“.$email”);
$stt->bind_参数(“s”,$hash);
$stt->bind_参数(“i”,$currTime+$expiryTime);
$stt->execute();
}
其他的
{
//返回给定的电子邮件地址与任何记录不匹配
}
//下面是将忘记的密码链接发送给用户的逻辑
}
函数checkHash($hash)
{
$row=null;
$currTime=time();
$bd=新bd();
$conn=$bd->connect();
$stt=$conn->prepare(“从恢复=?和恢复到期<$currTime的用户中选择*);
$stt->bind_参数(“s”,$hash);
$stt->execute();
$result=$stt->get_result();
if(mysqli_num_rows($result)==1)
{
$row=mysqli_fetch_array();
}
返回$row;
}

您可以在链接中包含发出请求的时间戳。然后,在处理密码恢复链接时,只需选中
abs(time()-$request\u time)@Pateman提供的保护非常非常少。任何人都可以编辑that@ThomWiggers,没错,但这是最简单的方法,因为他想避免在数据库中存储过期时间。唯一简单的方法是什么都不做Pateman,这同样安全:)“如果密钥泄漏”是的,很明显,但是密钥就像密码一样。如果泄露数据库密码,所有安全性都会失败。没有理由不使用它。