* Упражнение 2, 2015
Публикувано на 18 март 2015 в раздел ОСУП.
В това упражнение показваме login форма. Паролите са хеширани със salt (уникален ключ за всеки потребител в базата) и pepper (един общ salt в кода).
База от данни - мястото, където ще записваме потребителските имена и пароли. Създаваме си уникален потребител специално за login формата.
CREATE DATABASE upr2; USE upr2 CREATE TABLE users( id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, user VARCHAR(64) NOT NULL UNIQUE, pass CHAR(96) NOT NULL, salt CHAR(96) NOT NULL ); GRANT SELECT ON upr2.users TO loginform@localhost IDENTIFIED BY 'fghjudighfduishgiufdsw';
passgen.php - използвайте този скрипт, за да си генерирате insert заявки за вмъкване на потребители в базата данни
<?php
DEFINE("PEPPER", 'jfrikl^#@&*wsa^$#&*gjr__--eiu--AAa');
DEFINE("KEYSTRECHITERATIONS", 100000);
$user = "ivan";
$pass = "123456";
// Този salt определено е прекалено дълъг
// може да използвате значително по-къс
// без това да навреди на сигурността
$salt = base64_encode(openssl_random_pseudo_bytes(72));
for($i=0; $i<KEYSTRECHITERATIONS; $i++){
$pass = hash("sha384", $salt.$pass.PEPPER);
}
echo "INSERT INTO users(user, pass, salt)
VALUES('".$user."',
'".$pass."',
'".$salt."')";
?>
index.php - главната страница на сайта, в която показваме формата за вход.
<?php
session_start();
?>
<html><head><title>Login page</title></head>
<body>
<form action="login.php" method="POST">
USER: <input type="text" name="user" /><br />
PASS: <input type="password" name="pass" /><br />
<input type="submit" name="loginbutton" value="Login!" /><br />
</form><br />
<?php
if(isset($_SESSION['error'])){
echo $_SESSION['error'];
session_unset();
session_destroy();
}
?>
</body></html>
login.php - скрипта, който извършва автентикацията.
<?php
DEFINE("DBHOST", "localhost");
DEFINE("DBUSER", "loginform");
DEFINE("DBPASS", "fghjudighfduishgiufdsw");
DEFINE("DBNAME", "upr2");
DEFINE("PEPPER", 'jfrikl^#@&*wsa^$#&*gjr__--eiu--AAa');
DEFINE("HASHALGO", "sha384");
DEFINE("KEYSTRECHITERATIONS", 100000);
// Проверява дали има попълнена форма
function POSTVarsExists(){
return (isset($_POST['user'])
&& isset($_POST['pass'])
&& isset($_POST['loginbutton']));
}
// Проверява за валиден формат на името и паролата
// Приели сме потребителски имена от 4 до 64 букви/цифри
// и пароли от 6 до 64 символа (каквито и да е).
function userAndPassAreValidFormat($user, $pass){
return (is_string($user)
&& is_string($pass)
&& strlen($pass)>=6
&& strlen($pass)<=64
&& preg_match("/^[a-zA-Z0-9_-]{4,64}$/",$user));
}
// С тази функция се пренасочваме обратно към index.php
function backToIndex($error){
switch($error){
case 0: break;
case 1: session_start();
session_unset();
$_SESSION['error']
= "Invalid username OR password";
break;
case 2: session_start();
session_unset();
$_SESSION['error']
= "Technical issues. Come back later";
break;
}
header("Location: index.php");
}
// Ако не сме попълнили форма, се връщаме към index
if(!POSTVarsExists()){
backToIndex(0);;
exit;
}
// Ако сме попълнили име или парола, които не отговарят
// на стандартния формат, се връщаме към index с грешка
if(!userAndPassAreValidFormat(
$_POST['user'], $_POST['pass']
)){
backToIndex(1);
exit;
}
$user = $_POST['user'];
$pass = $_POST['pass'];
// Свързване с базата от данни
$link = @mysqli_connect(DBHOST,DBUSER,DBPASS,DBNAME);
if(!$link){
backToIndex(2);
exit;
}
// Това може да се пропусне
$user = @mysqli_real_escape_string($link, $user);
// Изпълняваме SQL заявка
$sql = "SELECT id, pass, salt
FROM users
WHERE '".$user."' = user
LIMIT 1";
$result = @mysqli_query($link, $sql);
if(!$result){
backToIndex(2);
@mysqli_close($link);
exit;
}
// Взимаме ред от резултата от заявката
$row = @mysqli_fetch_assoc($result);
// Ако няма върнат ред, това е невалидно име/парола
if(!isset($row['id'])){
backToIndex(1);
@mysqli_close($link);
exit;
}
// Хешираме подадената от потребителя парола
for($i=0; $i<KEYSTRECHITERATIONS; $i++){
$pass = hash(HASHALGO, $row['salt'].$pass.PEPPER);
}
// Ако не съвпада с паролата от БД, връщаме към index
if($pass !== $row['pass']){
backToIndex(1);
@mysqli_close($link);
exit;
}
// Ако всичко е наред, продължаваме към securearea
session_start();
session_unset();
session_regenerate_id(true);
$_SESSION['userid'] = $row['id'];
header("Location: securearea.php");
exit;
?>
securearea.php - мястото, където искаме да влезнем.
<?php
session_start();
if(!isset($_SESSION['userid'])){
header("Location: index.php");
exit;
}
?>
<html><head><title>Secure area</title></head>
<body>
<?= "Hello ".$_SESSION['userid'] ?>
</body></html>
Добави коментар