* Автоматична автентикация с некриптирано cookie
Публикувано на 20 ноември 2008 в раздел ОСУП.
Нека разгледаме прост скрипт, в който автентикираме потребител. В началото на файла ще стартираме потребителска сесия (като абстрактно ще използваме създадената в предишните статии функция security_start_session), за да сме сигурни, че няма фиксиране на сесия. При първоначално зареждане ще се извежда форма, питаща потребителя за име и парола. Тя ще изпраща информацията чрез POST към същия скрипт. При положение, че сме въвели вярна комбинация (проверявано от функцията checklogin), то ще запишем в сесията поле "authenticated" със стойност "1". Чрез това поле ще накараме скрипта да следи, дали случайно не сме въвели вече вярно име и парола и ако да - няма да извежда формата на екрана. Ето и примерен код:
<?php
function security_start_session($ssl, $timeout, $maxtime, $ip){
// ... security checks where we may destroy the session
session_start();
session_regenerate_id(true);
return 1;
}
if (security_start_session(0, 6*60, 20*60, 1) != 1){
echo "<br>session destroyed!";
return;
}
// Функция, която отпечатва формата в html кода
function showloginform(){
echo '<form action="cookie.php" method="POST">';
echo 'user:';
echo '<input type="text" name="user">';
echo '<br>pass:';
echo '<input type="password" name="pass">';
echo '<br><input type="submit" name="submit"';
}
// Функция, която проверява за вярност на име и парола
function checklogin($user, $pass){
if(!is_string($user) || !is_string($pass)) return 0;
if($user == "test" && $pass == "123456") return 1;
else return 0;
}
// Ако вече сме автентикирани, то сървъра
// е "запомнил" това в полето 'authenticated'
if($_SESSION['authenticated'] == 1){
echo '<html><head><title>WorldBank.dom login page</title></head><body>';
echo "Welcome back. I remember your session...";
}
else{
// Ако сме попълнили формата и сме натиснали Submit
if( isset($_POST['submit'])){
// Валидираме данните:
if (checklogin($_POST['user'], $_POST['pass']) == 1){
echo '<html><head><title>WorldBank.dom login page</title></head><body>';
echo "You are logged in successfully!";
$_SESSION['authenticated'] = 1;
}
else{
echo '<html><head><title>WorldBank.dom login page</title></head><body>';
echo "Invalid username and password";
}
}
// В противен случай влизаме за първи път
// и трябва да се изкара формата:
else{
showloginform();
}
}
?>
</body></html>
Големият недостатък тук, е че сесията е валидна до затварянето на браузъра на потребителя. За да го демонстрираме направете следният опит:
1. Отворете написаната страница и въведете вярно име и парола.
2. Отворете нов "tab" в браузъра със същата страница - ще забележите, че тя ви "помни".
3. Сега затворете браузъра напълно и отворете нов. Ще видите, че скрипта вече не ви "помни".
Както отбелязахме в много случаи е нужно да запазваме тази информация, за да може потребителя да влиза автоматично на нашия сайт. За целта ще използваме cookies:
<?php
function security_start_session($ssl, $timeout, $maxtime, $ip){
// ... security checks
session_start();
session_regenerate_id(true);
return 1;
}
if (security_start_session(0, 6*60, 20*60, 1) != 1){
echo "<br>session destroyed!";
return;
}
function showloginform(){
echo '<html><head><title>WorldBank.dom login page</title></head><body>';
echo '<form action="cookie.php" method="POST">';
echo 'user:';
echo '<input type="text" name="user">';
echo '<br>pass:';
echo '<input type="password" name="pass">';
// Добавяме html checkbox
echo '<br>Set cookie: ';
echo '<input type="checkbox" name="remember" value="true">';
echo '<br><input type="submit" name="submit"';
}
function checklogin($user, $pass){
if ($user == "test" && $pass == "123456") return 1;
else return 0;
}
// Проверяваме дали имаме записано cookie
if(isset($_COOKIE['user']) && isset($_COOKIE['pass'])){
// ако да - ще проверим дали данните в него са валидни
if (checklogin($_COOKIE['user'], $_COOKIE['pass']) == 1){
$_SESSION['authenticated'] = 1;
}
// Ако не са - ще ги изтрием
else{
setcookie("user","", mktime(12,0,0,1, 1, 1970));
setcookie("pass","", mktime(12,0,0,1, 1, 1970));
}
}
if($_SESSION['authenticated'] == 1){
echo '<html><head><title>WorldBank.dom login page</title></head><body>';
echo "Welcome back. I remember your session...";
}
else{
if( isset($_POST['submit'])){
if (checklogin($_POST['user'], $_POST['pass']) == 1){
// Ще "запомним" ли сесията с cookie?
if($_POST["remember"]=="true"){
setcookie("user",$_POST['user'], time()+3600);
setcookie("pass",$_POST['pass'], time()+3600);
}
echo '<html><head><title>WorldBank.dom login page</title></head><body>';
echo "You are logged in successfully!";
$_SESSION['authenticated'] = 1;
}
else{
echo '<html><head><title>WorldBank.dom login page</title></head><body>';
echo "Invalid username and password";
}
}
else{
showloginform();
}
}
?>
</body></html>
В този си вид модела на автентикация е относително сигурен. За cookie променахме, че най-големият проблем, е когато то се пренася през некриптиран канал. В случая бихме казали, че преди написаната функция secure_session_start(...) се грижи за контрола на канала на трафика. Това обаче е изключително грешен подход. Представете си, че разработвате приложение в екип от програмисти, като вие разработвате модула за управление на cookies, а ваш колега управлението на сесиите. Трябва ли вашият код да зависи от сигурността на кода на вашия колега? Ако погледнете отново кода ще видите, че дори в нашия пример сме задали стойност "0" на $ssl при извикването на security_session_start()!!! Не е ли по-добре да се погрижите и да се "преосигурите" с малко допълнителна защита? При сигурното програмиране параноята е полезна.
Горният код има и друг сериозен проблем със сигурността. Казахме, че cookies са файлове с обикновен текст. Ние не записахме ли паролата в него? Какво ще се случи ако някой успее да открадне това cookie от компютъра на наш потребител? Очевидно е че той ще има възможност за достъп до нашата система, но все пак не бихме искали поне да скрием истинският вид на паролата чрез някаква криптография. А можем ли да следим дали едно cookie е откраднато или не?
В следващата статия ще разгледаме методи за защита на cookies използвани за автентикация.
Добави коментар