понедельник, 25 сентября 2017 г.

Соцсеть. Напоминание пароля. Урок 9.

Напоминание пароля.
Алгоритм.

Пользователь может менять свой пароль, если он залогинен.
Либо он может менять свой пароль, если он его забыл. В этом случае, он вводит свой 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/forgot-password.php генерируется новый токен, который мы отображаем на странице, Например,
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>

Комментариев нет:

Отправить комментарий

Materialize-css. Футер

Сделаем футер и прижмем к низу страницы. Документация: https://materializecss.com/footer.html