Chyba nie ma osoby, która serfując po Internecie nie zetknęła by się z procesem autoryzacji (logowaniem) np: na forum, do poczty elektronicznej, konta na Facebooku itd. Zabieg ten polega na wypełnieniu formularza unikatowym loginem (najczęściej e-mailem) i hasłem uwierzytelniającym. Jeśli dane zostaną pozytywnie zweryfikowane użytkownik uzyskuje dostęp do określonych zasobów serwisu. Procesem odwrotnym jest wylogowanie, czyli usunięcie identyfikatora sesji z przeglądarki internetowej.
Hasło podane przez użytkownika podczas rejestracji konta powinno być „silne”, czyli trudne do złamania przez cyberprzestępców. Powinno składać się z dużych i małych liter, cyfr oraz znaków specjalnych. To oklepana reguła, którą należy stosować jeśli nie chcemy ułatwić roboty potencjalnemu włamywaczowi. Poza tym hasło powinno być zapisane do bazy w postaci zakodowanej (hashowanej). Do wyboru mamy kilka wewnętrznych funkcji języka PHP, np: SHA, MD5, CRYPT.
System autoryzacji, który zaprezentuję opiera się na obiektowym PHP (OOP). Do składowania rekordów wykorzystam serwer MySQL oraz uniwersalny sterownik PDO do komunikacji z bazą danych. Hasła w bazie będą hashowane podwójnie, algorytmami: sha1 i md5.
A teraz trochę praktyki. Zadanie rozpoczniemy od utworzenia tabeli users:
1 2 3 4 5 |
CREATE TABLE users ( id INT(6) UNSIGNED AUTO_INCREMENT PRIMARY KEY, login VARCHAR(50) NOT NULL, password VARCHAR(100) NOT NULL ) |
Kod klasy odpowiedzialnej za cały proces autoryzacji jest dosyć rozbudowany, ale nie musisz się w niego zagłębiać. Skopiuj go po prostu i zapisz pod nazwą: class.Authorization.php. W poszczególnych liniach kodu są moje komentarze i myślę, że to w zupełności wystarczy. Zakładam, że masz głowę na karku 😉
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
<?php /* e-spin.pl */ /* class.Authorization.php */ class Authorization { private $_user; private $_password; private $_dbpdo; // konstruktor pobiera identyfikator połączenia z bazą public function __construct() { try { global $pdo; $this->_dbpdo = $pdo; } catch(PDOException $error) { return $error->getMessage(); } } // ustawiamy metody dostępowe set i get public function setUser($user) { $this->_user = $user; } public function setPassword($password) { $this->_password = $password; } public function getUser() { return $this->_user; } public function getPassword() { return $this->_password; } // walidujemy pola formularza public function validateUsr() { if ( ($this->getUser())=='' || ($this->getPassword())=='' ) { return false; } else { return true; } } // hashujemy hasło public function Hash() { return sha1(md5($this->getPassword().$this->getPassword())); } public function Login() { $password = $this->Hash(); // sprawdzamy czy login i hasło są w tabeli users $sql = $this->_dbpdo->prepare("SELECT * FROM users WHERE login=:user AND password=:password LIMIT 1"); $sql->bindValue(':user',$this->getUser(),PDO::PARAM_STR); $sql->bindValue(':password',$password,PDO::PARAM_STR); $sql->execute(); // jeżeli znaleziono rekord to ustawiamy sesje if ($row = $sql->fetch()) { session_start(); $_SESSION['id_usr'] = $row['id']; $_SESSION['login_usr'] = $row['login']; // dobrą praktyką jest ponowne wygenerowanie identyfikatora sesji // ochroni nas to przed atakami session fixation ini_set('session.cookie_httponly', 1); return true; } else { return false; } // zamykamy połączenie z bazą $sql->closeCursor(); } // metoda wylogowuje użytkownika public function LogOut() { session_start(); session_unset(); // usuwamy sesje session_destroy(); // niszczymy sesje } } ?> |
Zapisz kolejny plik pod nazwą config.php. Jak się domyślasz zawiera on dane do połączenia z bazą MySQL:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
<?php /* config.php */ // parametry połączenia z bazą $db["Host"] = "localhost"; $db["User"] = "user"; $db["Password"] = "**********"; $db["Name"] = "baza"; function connect() { global $pdo; global $db; try { // dzięki PDO możemy połączyć się z dowolną bazą :) $pdo = new PDO('mysql:host='.$db["Host"].';dbname='.$db["Name"], $db["User"], $db["Password"]); $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); } catch(PDOException $error) { echo $error->getMessage(); } } ?> |
Ostatni już skrypt login.php uruchamiany jest wtedy, kiedy kliknięty zostanie przycisk „submit” formularza. Do tego skryptu dołączamy bibliotekę class.Authorization.php.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
<?php /* login.php */ if (isset($_POST["submit"])) { // jeżeli kliknięto przycisk formularza connect(); // nawiązujemy połączenie z bazą require_once 'class.Authorization.php'; // dołączamy klasę // pobieramy dane z pól formularza (user i password) $user = strip_tags(trim($_POST["user"])); $password = strip_tags(trim($_POST["password"])); // tworzymy egzemplarz klasy i ustawiamy zmienne do przetwarzania $log = new Authorization(); $log->setUser($user); $log->setPassword($password); // walidujemy dane if (!$log->validateUsr()) { echo '<p class="error">Wprowadź login i hasło!</p>'; } else if (!$log->Login()) { echo '<p class="error">Nieprawidłowy login i/lub hasło!</p>'; } else { session_start(); header('Location: main.phtml'); // jeśli autoryzacja jest poprawna robimy przekierowanie na stronę main.phtml // lub cokolwiek innego... } } ?> |
Na koniec tworzymy szablon HTML z formularzem logowania o nazwie login.phtml. Gdzieś wewnątrz sekcji BODY doklejamy skrypty: config.php i login.php.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>Logowanie</title> </head> <body> <form action="" method="post"> <fieldset> <legend>Logowanie</legend> <?php // dołączamy plik konfiguracyjny oraz skrypt logowania require_once 'config.php'; include 'login.php'; ?> <input type="text" name="user" maxlength="30" placeholder="Login" required autofocus /> <input type="password" name="password" maxlength="30" placeholder="Hasło" required /> <button type="submit" name="submit">zaloguj mnie</button> </fieldset> </form> </body> </html> |
I gotowe. Otwórz w przeglądarce stronę login.phtml i zrób test. Tabela users jest pusta, tak więc próby zalogowania się spełzną na niczym. Możemy wprowadzić do tabeli kilka rekordów w ten sposób:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<?php /* insert.php */ require_once 'config.php'; connect(); $password = 'hasło'; $password_hash = sha1(md5($password.$password)); $add = $pdo->exec("INSERT INTO users (login,password) VALUES ('admin','$password_hash')"); $add->closeCursor(); ?> |
Żeby aplikacja była kompletna pasuje jeszcze do strony main.phtml dodać przycisk „wyloguj”, który usunie sesję użytkownika i przeniesie go z powrotem do strony logowania. W tym celu można użyć funkcji LogOut() zawartej w klasie.
1 |
<?php LogOut(); ?> |