Jak zrobić proste logowanie w PHP dla jednego użytkownika (administratora)?

Treść dodana: 18 listopada 2017. Ostatnia modyfikacja: 05 grudnia 2017.

Bardzo często zachodzi konieczność zablokowania dostępu do pewnych części strony dla niezalogowanego użytkownika. Nie trzeba przy tym tworzyć zaawansowanych reguł ACL. Dzisiaj pokażę podstawowy skrypt logowania tylko dla jednego użytkownika – niech będzie to nasz główny administrator systemu. W celach podglądowych utworzymy 3 pliki:

|- logowanie.php   // formularz logowania, weryfikacji danych i wylogowania
|- haslo.php       // prosty plik zawierający hasło użytkownika
|- strona.php      // dodatkowa strona na której sprawdzimy działanie

Zacznijmy od pliku `haslo.php`. Niech zwraca ono prostą tablicę z jednym kluczem `pass` które zawierać będzie zahashowany funkcją password_hash string z naszym hasłem. Hasło należy wygenerować wcześniej poleceniem:

<?php
echo password_hash('nasze_haslo', PASSWORD_BCRYPT);

W moim przypadku powyższy kod zwrócił:

$2y$10$4kVycr7Kija5n8oKu8hom.H3hoBnU3t715y/gqa74INM8t2cAEcyi

Trzeba pamiętać że ciąg znaków generowany przez funkcję `password_hash()` będzie za każdym razem inny. String ten zapisujemy do pliku

haslo.php

<?php
return [
    'pass' => '$2y$10$4kVycr7Kija5n8oKu8hom.H3hoBnU3t715y/gqa74INM8t2cAEcyi'
];

Hasło warto jest zabezpieczać zawsze, niezależnie od poziomu skomplikowania skryptu. Kolejnym krokiem będzie utworzenie strony logowania / wylogowania. Ponieważ mamy w systemie tylko jednego użytkownika nie będziemy sprawdzać jego loginu (chociaż oczywiście można to zrobić) a wyłącznie samo hasło. W pliku `logowanie.php` utworzymy prosty formularz:

logowanie.php

<?php
// Ustawiamy odpowiedni nagłówek dla kodowania treści
header("Content-Type: text/html; charset=UTF-8");
// Rozpoczynamy sesję
session_start();

// tutaj umieścimy kod sprawdzający

// sprawdzamy czy użytkownik jest zalogowany (true), lub zwracamy false
$is_admin = $_SESSION['admin'] ?? false;
?>

<!DOCTYPE html>
<html lang="pl">
<head>
    <meta charset="UTF-8"/>
    <title>Podaj dane logowania</title>
</head>
<body>
    <main>
        <?php if (!$is_admin): ?>
        <p>Aby kontynuować musisz podać hasło:</p>
        <form action="" method="POST">
            <input name="pass" type="password" placeholder="Podaj hasło"/>
            <button name="login" type="submit">Zaloguj się</button>
        </form>
    <?php else: ?>
        <form action="" method="POST">
            <button name="logout" type="submit">Wyloguj się</button>
        </form>
    <?php endif; ?>
    </main>
</body>
</html>

Do pliku warto też dołączyć ogólną konfigurację PHP opisaną we wcześniejszym poradniku – w szczególności tę dotyczącą konfiguracji ustawień sesji. W pliku, po ustawieniu odpowiednich nagłówków, startujemy sesję i sprawdzamy czy użytkownik jest zalogowany. Następnie, w zależności od wyniku zmiennej `$is_admin`, generujemy formularz logowania / wylogowania. Wykorzystałem alternatywną składnię struktur kontrolnych, która jest znacznie bardziej przejrzysta w połączeniu z szablonami HTML.

Jak teraz połączyć dane wprowadzone w formularzu z logiką skryptu? Po linii z `session_start();` a przed `$is_admin` wstaw następujący kod:

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    if(isset($_POST['login'])) {
        // można dodatkowo wyświetlić odpowiedni komunikat jeżeli hasło jest puste
        $pass = $_POST['pass'] ?? null;
        $admin_hash = require_once 'haslo.php';
        // możemy nadpisać tablicę samym hasłem
        $admin_hash = array_key_exists('pass', $admin_hash) ? $admin_hash['pass'] : null;
        if (!empty($pass) && password_verify($pass, $admin_hash)) {
            $_SESSION['admin'] = true;
            echo '<p>Poprawnie zalogowano.</p>';
        } else {
            echo '<p>Hasło nie pasuje!</p>';
        }
    } elseif (isset($_POST['logout'])) {
        $_SESSION['admin'] = false;
        session_regenerate_id();
    }
}

Oba formularze wysyłamy metodą POST. Sprawdzamy zatem w pierwszej linii czy taką metodą skrypt odebrał dane. Następnie w zależności od klikniętego przycisku (login / logout) różnicujemy kod. Przy wylogowaniu ustawiamy zmienną sesyjną `admin` na `false` oraz regenerujemy id sesji. Warto tak postępować zabezpieczając się przed niektórymi atakami. Dla wysłanego buttona o nazwie `login` wczytujemy plik `haslo.php`, sprawdzamy czy istnieje w załadowanej tablicy klucz `pass`, a na samym końcu porównujemy funkcją password_verify wprowadzone hasło z zapisanym hashem. Gdy hasło jest poprawne, ustawiamy zmienną sesyjną `admin` na `true` oraz wyświetlamy odpowiednie komunikaty. Można by w warunku ustawić dodatkową zmienną (Boolean) dla komunikatów i sprawdzać ją w kodzie niżej. Dzięki temu kod HTML byłby w jednym miejscu, natomiast logika w innym.

Pora przygotować dodatkową treść z pliku

strona.php

<?php
header("Content-Type: text/html; charset=UTF-8");
session_start();
$is_admin = $_SESSION['admin'] ?? false;
?>

<p>Treść dla zwykłego użytkownika</p>

<?php if ($is_admin): ?>
<p>Dodatkowa treść dla administratora</p>
<?php endif; ?>

Plik zawiera prostą treść i część warunków zapisanych wcześniej. Dla administratora dodajemy ukryty dla innych użytkowników paragraf. O czym warto zawsze pamiętać to fakt, że w każdym pliku w którym chcemy wykorzystywać sesję, należy ją wcześniej wystartować funkcją `session_start()`. Inaczej jej dane nie będą dostępne.

Podsumowanie

Na dość prostym przykładzie poznaliśmy bezpieczne sposoby przechowywania haseł oraz logikę aplikacji przy formularzu logowania. Gdybyśmy jeszcze chcieli dodać nazwę użytkownika, można ją uzupełnić w pliku `haslo.php`:

<?php
return [
    'login' => 'janek',
    'pass' => '$2y$10$4kVycr7Kija5n8oKu8hom.H3hoBnU3t715y/gqa74INM8t2cAEcyi'
];

i sprawdzić później czy ta podana w nowym polu formularza pasuje do pobranej z tablicy. Pojedyncze hasło równie dobrze można zwrócić jako string:

return '$2y$10$4kVycr7Kija5n8oKu8hom.H3hoBnU3t715y/gqa74INM8t2cAEcyi';

To do Ciebie Czytelniku należy decyzja jak to finalnie wykonać. Bardziej zaawansowanym programistom zalecam jeszcze lekturę wcześniejszego artykułu o systemie logowania.

Komentarze

Nie ma jeszcze żadnych komentarzy do wyświetlenia. Może chcesz zostać pierwszą osobą która podzieli się swoją opinią?

Dodaj komentarz

*
Nazwa zostanie wyświetlona wraz z komentarzem. Możesz też utworzyć nowe konto w serwisie, dzięki czemu uzyskasz dodatkową funkcjonalność.
*
Akceptowana jest ograniczona składnia Textile. Wszystkie tagi HTML zostaną usunięte.