Напоминание пароля.
Алгоритм.
Пользователь
может менять свой пароль, если он
залогинен. 
Либо он может
менять свой пароль, если он его забыл.
В этом случае, он вводит свой e-mail
и ему на почту приходит ссылка со
сгененрированным токеном. Этот токен
подставляется с get-параметр.
Если токен неверный, то нам выдает
сообщение Token invalid. Если верный, то
открывается страница смены пароля.
После смены пароля сгенерированный
токен удаляется из БД.
Создадим таблицу в
БД password_tokens.
id int(11)
unsigned primary AI
token char(64)
unique
user_id int(11)
unsigned 
Создадим страницу
forgot-password.php
<?php
   
include('./classes/DB.php');      
   
if(isset($_POST['resetpassword'])) {
        //
Генерируем токен.
        $cstrong =
true; 
        $token =
bin2hex(openssl_random_pseudo_bytes(64, $cstrong)); // мы
генерируем 64 байта, вторым параметром
передается только перемена
        $email =
$_POST['email'];        
        $user_id =
DB::query('SELECT id FROM users WHERE email=:email',
array(':email'=>$email))[0]['id'];
       
//DB::query('INSERT INTO password_tokens VALUES (\'\', :token,
:user_id)', array(':token'=>sha1($token), ':user_id'=>$user_id));
        // Вставка
в таблицу password_tokens сгенерированного
токена и id пользователя
       
DB::query('INSERT INTO password_tokens VALUE (:id, :token,
:user_id)', array(':id'=>null, ':token'=>sha1($token),
':user_id'=>$user_id));
        echo
'Email sent!';
        echo '<br
/>';
        echo
$token;
    }
?>
<h1>Forgot
Password</h1>
<form
action="forgot-password.php" method="post">
    <input
type="text" name="email" value=""
placeholder="Email..."/>
    <input
type="submit" name="resetpassword" value="Reset
Password"/>
</form>
Зайдем на
страницу change-password.php и проверим передан
ли этот вновь сгенерированный токен в
get-параметрах.
Например
так:
http://newsocial.loc/change-password.php?token=c215839f1080d74f2f387a52d20325634e6839ce
На
странице http://newsocial.loc/forgot-password.php
генерируется новый токен, который мы
отображаем на странице, Например,
9afcba54b8e9a67fc02d2c4293924b478798781c6677ea0481a4fe9813cc6ec96cdbde12c8e54c0fa7ac7d1efdcf07d3ab23e4882c4053b5f150b468be99abf4
9afcba54b8e9a67fc02d2c4293924b478798781c6677ea0481a4fe9813cc6ec96cdbde12c8e54c0fa7ac7d1efdcf07d3ab23e4882c4053b5f150b468be99abf4
И
теперь на странице смены пароля мы
передаем этот токен в get-параметрах
http://newsocial.loc/change-password.php?token=9afcba54b8e9a67fc02d2c4293924b478798781c6677ea0481a4fe9813cc6ec96cdbde12c8e54c0fa7ac7d1efdcf07d3ab23e4882c4053b5f150b468be99abf4
Если
этот токен неверный, то выводится Invalid
token.
Изменим страницу
change-password.php
<?php
   
include('./classes/DB.php');
   
include('./classes/Login.php');
   
if(Login::isLoggedIn()) {
       
if(isset($_POST['changepassword'])) {
           
$oldpassword = $_POST['oldpassword'];
           
$newpassword = $_POST['newpassword'];
           
$newpasswordrepeat = $_POST['newpasswordrepeat'];
           
$userid = Login::isLoggedIn();
            //
верифицируем пароль
            if
(password_verify($oldpassword, DB::query('SELECT password FROM users
WHERE id=:userid', array(':userid'=>$userid))[0]['password'])) { 
                //
проверяем совпадение пароля и его
повтора
               
if($newpassword == $newpasswordrepeat) {
                  
 if(strlen($newpassword) >= 6 && strlen($newpassword) <=
60) {
                  
     DB::query('UPDATE users SET password=:newpassword WHERE
id=:userid', array(':newpassword'=>password_hash($newpassword,
PASSWORD_BCRYPT), ':userid'=>$userid));
                  
     echo 'Password changed successfully!';
                  
 }
                }
else {
                  
 echo 'Password don\'t match';
                }
            } else
{
               
echo 'Incorrect old password!';
            }
        }
    } else {
       
$tokenIsValid = False; // токен неверный
       
if(isset($_GET['token'])) {
            $token
= $_GET['token'];
           
if(DB::query('SELECT user_id FROM password_tokens WHERE
token=:token', array(':token'=>sha1($token)))[0]['user_id']) {
               
$userid = DB::query('SELECT user_id FROM password_tokens WHERE
token=:token', array(':token'=>sha1($token)))[0]['user_id'];
               
$tokenIsValid = True; // токен верный
               
if(isset($_POST['changepassword'])) {        
                  
 $newpassword = $_POST['newpassword'];
                  
 $newpasswordrepeat = $_POST['newpasswordrepeat'];  
                  
     // проверяем совпадение пароля и его
повтора
                  
     if($newpassword == $newpasswordrepeat) {
                  
         if(strlen($newpassword) >= 6 &&
strlen($newpassword) <= 60) {
                  
             DB::query('UPDATE users SET password=:newpassword WHERE
id=:userid', array(':newpassword'=>password_hash($newpassword,
PASSWORD_BCRYPT), ':userid'=>$userid));
                  
             echo 'Password changed successfully!';
                  
             // После смены пароля, удалим
созданный токен
                  
             DB::query('DELETE FROM password_tokens WHERE
user_id=:userid', array(':userid'=>$userid));
                  
         }
                  
     } else {
                  
         echo 'Password don\'t match';
                  
     }       
                } 
              
            } else
{
               
die('Token invalid');
            }
        } else {  
 
           
die('Not logged in');
        }
    }
?>
<h1>Change
your Password</h1>
<form
action="<?php if(!$tokenIsValid) {echo 'change-password.php';
} else { echo 'change-password.php?token='.$token.''; } ?>"
method="post">
    <?php if
(!$tokenIsValid) { echo '<input type="password"
name="oldpassword" value="" placeholder="Current
Password ..."><p />'; } ?>
    <input
type="password" name="newpassword" value=""
placeholder="New Password..."/><br />
    <input
type="password" name="newpasswordrepeat" value=""
placeholder="Repeat Password..."/><br />
    <input
type="submit" name="changepassword" value="Change
Password"/>
</form>
 
Комментариев нет:
Отправить комментарий