Sprawny system logowania jest podstawą mającej dobrze funkcjonować witryny internetowej. Aby taki wykonać, należy użyć HTML i skryptów PHP. Cały mechanizm działa w kilku plikach, oraz wymaga bazy danych przechowującej przesyłane przez formularz informacje.

Najważniejszym w tym zestawie plikiem jest plik zaloguj.php, który przetwarza informacje podesłane przez formularz.

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
session_start();

if ((!isset($_POST['login'])) || (!isset($_POST['haslo'])))
{
header('Location: index.php');
exit();
}

require_once "polacz.php";

$polaczenie = @new mysqli($serwer, $uzytkownik, $haslo, $baza);

if ($polaczenie->connect_errno!=0)
{
echo "Error: ".$polaczenie->connect_errno;
}
else
{
$login = $_POST['login'];
$haslo = $_POST['haslo'];

$login = htmlentities($login, ENT_QUOTES, "UTF-8");
$haslo = htmlentities($haslo, ENT_QUOTES, "UTF-8");

if ($rezultat = @$polaczenie->query(
sprintf("SELECT * FROM skille WHERE uczen='%s' AND haslo='%s'",
mysqli_real_escape_string($polaczenie,$login),
mysqli_real_escape_string($polaczenie,$haslo))))
{
$ilu_userow = $rezultat->num_rows;
if($ilu_userow>0)
{
$_SESSION['zalogowany'] = true;

$wiersz = $rezultat->fetch_assoc();
$_SESSION['id'] = $wiersz['id'];
$_SESSION['uczen'] = $wiersz['uczen'];
$_SESSION['skill'] = $wiersz['skill'];
$_SESSION['poziom1'] = $wiersz['poziom1'];
$_SESSION['poziom2'] = $wiersz['poziom2'];
$_SESSION['poziom3'] = $wiersz['poziom3'];
$_SESSION['wynik'] = $wiersz['wynik'];

unset($_SESSION['blad']);
$rezultat->free_result();
header('Location: panel.php');

} else {

$_SESSION['blad'] = '<span style="color: red">Nieprawidłowy login lub hasło!</span>';
header('Location: index.php');

}

}

$polaczenie->close();
}

Omówmy teraz poszczególne części kodu. Na razie opuścimy sobie pierwsze kilka linijek kodu, a przejdziemy do następującej linijki. Do poprzednich wrócimy.

1
require_once "polacz.php";

Ta linijka zapewnia dołączenie składni innego programu, w tym wypadku jest to plik polacz.php. Instrukcja require_once działa podobnie, jak instrukcja include. Jest jednak różnica. require_once zapewnia, że plik nie musi być dołączany wielokrotnie, a tylko raz. Dodatkowo w razie nieodnalezienia pliku podanego w ścieżce, program pokaże nam błąd krytyczny, nie ostrzeżenie, jak w przypadku instrukcji include.

1
2
3
4
5
6
$polaczenie = @new mysqli($serwer, $uzytkownik, $haslo, $baza);

if ($polaczenie->connect_errno!=0)
{
echo "Error: ".$polaczenie->connect_errno;
}

Z powyższego kodu wynika, że zastosowano nową bibliotekę mysqli. Znak @ oznacza „wyciszenie” komunikatu o błędzie, gdyby taki się pojawił. Pętla if sprawdza, czy wystąpił błąd w połączeniu. Jeśli tak, program wyświetli kod błędu, aby użytkownik mógł zidentyfikować ten problem szybciej.

1
2
3
4
5
6
7
$login = htmlentities($login, ENT_QUOTES, "UTF-8");
$haslo = htmlentities($haslo, ENT_QUOTES, "UTF-8");

if ($rezultat = @$polaczenie->query(
sprintf("SELECT * FROM skille WHERE uczen='%s' AND haslo='%s'",
mysqli_real_escape_string($polaczenie,$login),
mysqli_real_escape_string($polaczenie,$haslo))))

Ten fragment zawiera zapytanie SQL. Nie byłoby w nim nic nietypowego, gdyby nie obecność kilku ciekawych zapisków. htmlentities, mysqli_real_escape_string oraz %s zamiast nazwy zmiennej PHP. Odgrywają rolę zabezpieczającą. Niezabezpieczone formularze wykorzystujące bazę danych, są narażone na tzw. SQL Injection. Jest to sztuczka wykorzystująca lukę w zabezpieczeniach, pozwalająca osobie wypełniającej formularz na zmanipulowanie zapytania SQL. Dzięki temu, może dostać się na dowolne konto znajdujące się w bazie. Jeśli chcemy, aby nasz formularz był chociaż w najprostszym stopniu zabezpieczony, zastosowanie tych poleceń będzie dobrym wyjściem.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$ilu_userow = $rezultat->num_rows;
if($ilu_userow>0)
{
$_SESSION['zalogowany'] = true;

$wiersz = $rezultat->fetch_assoc();
$_SESSION['id'] = $wiersz['id'];
$_SESSION['uczen'] = $wiersz['uczen'];
$_SESSION['skill'] = $wiersz['skill'];
$_SESSION['poziom1'] = $wiersz['poziom1'];
$_SESSION['poziom2'] = $wiersz['poziom2'];
$_SESSION['poziom3'] = $wiersz['poziom3'];
$_SESSION['wynik'] = $wiersz['wynik'];

unset($_SESSION['blad']);
$rezultat->free_result();
header('Location: panel.php');

}

Pierwsza linijka właściwie nie jest niezbędna, tak samo jak sama pętla, jednak jej zawartość jest już kluczowa do działania. Jej działanie ogranicza się do sprawdzania, ile wierszów w bazie odpowiada danemu poprzednio zapytaniu SQL. Wiadomo, że w systemie logowania dla podanego loginu i hasła może być albo zero albo jeden wynik, stąd zapisek $ilu_userow>0 tak naprawdę jest tylko asekuracyjny i równie dobrze mogłoby to być $ilu_userow==1.
Widzimy tu także wykorzystanie zmiennych sesyjnych, które są kluczowe przy takich systemach logowaniach. POST czy GET przesyłają dane tylko do pliku przetwarzającego formularz, i nigdzie dalej. Natomiast SESSION zapewnia zasięg zmiennym w każdym pliku, w którym występuje polecenie session_start();.

1
2
3
4
5
6
else {

$_SESSION['blad'] = '<span style="color: red">Nieprawidłowy login lub hasło!</span>';
header('Location: index.php');

}

Zmienna blad ma zastosowanie w przypadku, gdy zapytanie nie zwraca żadnego wyniku, czyli nie ma takiego użytkownika w bazie. Zaraz po tym jesteśmy z powrotem przekierowani do formularza.

Do formularza musimy dodać:

1
2
3
4
5
6
7
session_start();

if ((isset($_SESSION['zalogowany'])) && ($_SESSION['zalogowany']==true))
{
header('Location: panel.php');
exit();
}

Ten skrypt działa, gdy będąc zalogowanym, będziemy chcieli z poziomu adresu URL przejść na adres formularza. Ustawiona w pliku przetwarzającym formularz zmienna zalogowany przyjmuje wartość true, jeśli zalogowanie przeszło pomyślnie. Zatem pełni ona role sprawdzająca, czy użytkownik jest zalogowany, i wtedy aby móc wrócić do formularza, będzie musiał się wylogować.

W pliku odpowiadającym za wylogowanie znajduję się taki skrypt:

1
2
3
4
5
session_start();

session_unset();

header('Location: index.php');

Jak widać, jest krótki i prosty. Czyści on zawartość wszystkich zmiennych sesyjnych, co powoduje, że cała procedura począwszy od zalogowania, zaczyna się od początku, nie pozostawiając śladów po poprzednim użytkowniku.

Wróćmy jeszcze do ominiętych kilku pierwszych linijek w pliku przetwarzającym formularz.

1
2
3
4
5
6
7
session_start();

if ((!isset($_POST['login'])) || (!isset($_POST['haslo'])))
{
header('Location: index.php');
exit();
}

Skrypt ten sprawdza, czy zmienne login lub haslo przyjęły jakieś wartości, czyli czy są „ustawione”, jak wskazuje na to nazwa polecenia isset. Widzimy tam znaki negacji, co oznacza, że skrypt działa, gdy obie te zmienne pozbawione są wszelkich informacji. Jest to także mechanizm zabraniający przechodzenia pomiędzy plikami z poziomu adresu URL, tylko tym razem, gdy nie jest zalogowany żaden użytkownik. exit powoduje opuszczenie przez interpreter kodu jego reszty, aby zaoszczędzić czas i przyśpieszyć wykonanie instrukcji zawartej w pętli.

Tak działający system logowania za pewne nie jest pozbawiony wad, ale na początek wypełnia dobrze swoje zadanie.

PHP