Načrtovanje in razvoj spletnih aplikacij

Prijava na zaščitene strani

Pri prijavi uporabnik v obrazec vnese uporabniško ime in geslo. Aplikacija nato preveri, ali tak uporabnik obstaja in ali vneseno geslo ustreza shranjenemu geslu v podatkovni zbirki.

Prijava uporabnika v aplikacijo

Prijava je pomemben del spletne aplikacije, saj z njo omejimo dostop do zaščitenih strani. Po uspešni prijavi uporabnika navadno shranimo v sejo in mu omogočimo dostop do administrativnega ali uporabniškega dela aplikacije.

Pri prijavi običajno izvedemo naslednje korake:

  1. uporabnik izpolni obrazec za prijavo,
  2. aplikacija poišče uporabnika v bazi,
  3. preveri se pravilnost gesla,
  4. po uspešni prijavi se ustvarijo oziroma nastavijo podatki v seji,
  5. uporabnik se preusmeri na zaščiteno stran.

Gesel v bazi ne shranjujemo v navadnem besedilu, ampak kot varne zgoščene vrednosti. Pri prijavi zato uporabimo funkcijo za preverjanje gesla, ne pa neposredne primerjave z navadnim nizom.

Osnovni primer z mysqli

Spodnji zgled prikaže osnovno prijavo uporabnika z uporabo mysqli, seje in preverjanja gesla z password_verify().

<?php
session_start();

define('DB_SERVER', 'localhost');
define('DB_USER', 'uporabnik');
define('DB_PASS', 'skritoGeslo');
define('DB_NAME', 'knjiznica');

$connection = mysqli_connect(DB_SERVER, DB_USER, DB_PASS, DB_NAME);

if (!$connection) {
    die(
        'Povezava s podatkovno zbirko ni vzpostavljena: ' .
        mysqli_connect_error() .
        ' (' . mysqli_connect_errno() . ')'
    );
}

$napaka = '';

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $username = trim($_POST['username'] ?? '');
    $passwordAttempt = trim($_POST['password'] ?? '');

    if ($username === '' || $passwordAttempt === '') {
        $napaka = 'Vpišite uporabniško ime in geslo.';
    } else {
        $stmt = mysqli_prepare(
            $connection,
            "SELECT id, username, password FROM users WHERE username = ?"
        );

        mysqli_stmt_bind_param($stmt, 's', $username);
        mysqli_stmt_execute($stmt);
        $result = mysqli_stmt_get_result($stmt);
        $user = mysqli_fetch_assoc($result);

        if (!$user || !password_verify($passwordAttempt, $user['password'])) {
            $napaka = 'Uporabniško ime ali geslo ni pravilno.';
        } else {
            session_regenerate_id(true);
            $_SESSION['user_id'] = (int)$user['id'];
            $_SESSION['logged_in'] = time();

            header('Location: admin.php');
            exit();
        }

        mysqli_stmt_close($stmt);
    }
}

mysqli_close($connection);
?>

Osnovni primer s PDO

Tudi z vmesnikom PDO prijavo izvedemo s pripravljeno poizvedbo, nato pa geslo preverimo s funkcijo password_verify().

<?php
session_start();

$streznik = 'localhost';
$baza = 'knjiznica';
$uporabnik = 'uporabnik';
$geslo = 'skritoGeslo';

try {
    $pdo = new PDO("mysql:host=$streznik;dbname=$baza;charset=utf8mb4", $uporabnik, $geslo);
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    $napaka = '';

    if ($_SERVER['REQUEST_METHOD'] === 'POST') {
        $username = trim($_POST['username'] ?? '');
        $passwordAttempt = trim($_POST['password'] ?? '');

        if ($username === '' || $passwordAttempt === '') {
            $napaka = 'Vpišite uporabniško ime in geslo.';
        } else {
            $stmt = $pdo->prepare(
                "SELECT id, username, password
                 FROM users
                 WHERE username = :username"
            );
            $stmt->bindValue(':username', $username, PDO::PARAM_STR);
            $stmt->execute();

            $user = $stmt->fetch(PDO::FETCH_ASSOC);

            if (!$user || !password_verify($passwordAttempt, $user['password'])) {
                $napaka = 'Uporabniško ime ali geslo ni pravilno.';
            } else {
                session_regenerate_id(true);
                $_SESSION['user_id'] = (int)$user['id'];
                $_SESSION['logged_in'] = time();

                header('Location: admin.php');
                exit();
            }
        }
    }
}
catch (PDOException $e) {
    $napaka = 'Prijava trenutno ni mogoča.';
}
?>

Varnost pri prijavi

Prijava mora biti izvedena varno, saj z njo ščitimo dostop do uporabniških podatkov in administrativnega dela aplikacije.

  • gesla morajo biti v bazi shranjena kot hash,
  • geslo preverjamo s funkcijo password_verify(),
  • po uspešni prijavi je priporočljivo izvesti session_regenerate_id(true),
  • v sejo shranimo le podatke, ki jih res potrebujemo,
  • ob napaki uporabniku pokažemo splošno sporočilo, ne tehničnih podrobnosti.

Pomembnosti pri prijavi uporabnika

  • uporabimo obrazec za vnos uporabniškega imena in gesla,
  • uporabnika poiščemo v tabeli uporabnikov,
  • gesla nikoli ne primerjamo kot navadno besedilo,
  • po uspešni prijavi podatke shranimo v $_SESSION,
  • uporabnika po prijavi navadno preusmerimo na zaščiteno stran.

📘Aplikacija Knjige

V priloženi aplikaciji je prijava izvedena v datoteki 15_login.php. Datoteka najprej zažene sejo in preveri, ali je uporabnik že prijavljen. Če je, ga takoj preusmeri na administrativno stran.

Ob oddaji obrazca aplikacija prebere uporabniško ime in geslo, nato pa s pripravljeno PDO poizvedbo poišče uporabnika v tabeli users. Če uporabnik ne obstaja ali geslo ni pravilno, se izpiše splošno sporočilo o napačni prijavi.

Po uspešni prijavi aplikacija regenerira ID seje, v sejo shrani identifikator uporabnika in čas prijave, nato pa uporabnika preusmeri na zaščiteno administrativno stran. Na strani sta prikazani tudi povezavi za registracijo in za zamenjavo gesla.

Primer: aplikacija – 15_login.php

Navodila za izdelavo prijave

  1. Najprej pripravimo obrazec za uporabniško ime in geslo.
  2. Ob oddaji obrazca preberemo oba podatka.
  3. Preverimo, ali sta obe polji izpolnjeni.
  4. S pripravljeno poizvedbo v bazi poiščemo uporabnika po uporabniškem imenu.
  5. Geslo preverimo s funkcijo password_verify().
  6. Po uspešni prijavi regeneriramo ID seje in v $_SESSION shranimo potrebne podatke.
  7. Uporabnika preusmerimo na zaščiteno stran aplikacije.

Pri učenju je smiselno poznati oba pristopa:

  • mysqli za klasično prijavo s pripravljenimi stavki,
  • PDO za sodobnejši pristop pri delu z bazo,
  • aplikacijski pristop, kjer prijava, seja in preusmeritev skupaj sestavljajo zaščito administrativnega dela.