* Автоматична автентикация с некриптирано 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 използвани за автентикация.
Добави коментар