Blue Flower

In questo articolo vedremo un esempio pratico per gestire il Login/Logout di un utente. L'esempio è puramente didattico. Per un approccio "professionale e sicuro" al problema si consigli di utilizzare un framework PHP titpo CodeIgniter o similare (vedi articolo su CodeIgniter).

Useremo gli esempi Bootstrap 4 per i template e NetBeans IDE per lo sviluppo (demo).

Cosa ci serve:

* XAMPP
* NetBeans IDE
* Database con tabella utenti (users) popolata (almeno 2-3 record)con PW crittografata MD5
* phpMyAdmin per ispezionare DB e tabella (nomi campi e dati)
* Dati di accesso al database (per MySQL su XAMPP in locale):
    - host=localhost
    - username=root
    - password="" (vuota!)
    - nome DB=esempio2 (nel mio caso)

Link per progetto:

(1) Boostrap 4 Home Page-Login-Dashboard: https://getbootstrap.com/docs/4.0/examples/
(2) PHP MySQL Database: https://www.w3schools.com/php/php_mysql_intro.asp
(3) PHP Sessioni: https://www.w3schools.com/php/php_sessions.asp

(1) Risorse utilizzate del file: bootstrap-4.0.0.zip
* cartelle:  dist e assets (complete)
* cartelle: sticky-footer-navbar; sign-in; dashboard; presenti in bootstrap-4.0.0\docs\4.0\examples
(2): PHP MySQL Select Data-->HTML table:Example (MySQLi Object-oriented)-->2 esempio Object-oriented
(3) Destroy a PHP Session

Procediamo

Preparazione dei template Bootstrap 4

  • Lanciamo XAMPP ed attiviamo Apache e MySQL
  • Lanciamo NetBeans IDE e creiamo un nuovo progetto PHP (nell'esempio: ClaudioShop)
  • Scarichiamo e scompattiamo gli esempi Bootstrap 4 (link 1)
  • Copiamo le cartelle dist e assets nella root del nostro progetto
  • Andiamo in bootstrap-4.0.0\docs\4.0\examples
  • Entriamo nella cartella: sticky-footer-navbar e copiamo il file sticky-footer-navbar.css nella root del nostro progetto
  • Eseguire (doppio click) il file index.html per vedere come si presenta il template
  • Apriamo con un editor di testo il file index.html e copiamone il contenuto nell'index.php del nostro progetto (la nostra Home Page)
  • Modifichiamo nel file index.php i percorsi di caricamento delle librerie in accordo al nostro progetto (togliere tutti i ../../../ ecc.) e verificare che la pagina si veda correttamente
  • Andare nella cartella Sign-in di Boostrap4 examples
  • Creare una nuova pagina di nome login.php ed incollarci dentro il contenuto del file index.html della cartella e copiare il file signin.css nella root. Modificare il codice per il caricamento corretto delle librerie e verificare che la pagina si veda correttamente
  • Andare nella cartella Dashboard di Bootstrap examples
  • Creare una nuova pagina dashboard.php ed incollarci dentro il contenuto del file index.html e copiare il relativo css nella root del progetto. Modificare il codice per il caricamento delle librerie e verificare che la pagina si veda correttamente
  • Modificare  una voce di menu di index.php in modo che punti a login.php (<a class="nav-link" href='login.php'>Login</a>)
  • Modificare il file login.php aggiungendo: method="post" action="login.php" al tag FORM e gli attributi name="email" e name="password" ai rispettivi tag INPUT

Creazione o Importazione del database

  • Aprire il browser e digitare localhost. Quindi dal menu di XAMPP avviare phpMyAdmin.
  • Creare un nuovo database (esempio2 nel tutorial) ed una nuova tabella (utenti nel tutorial) con almeno due campi: username e password
  • Inserire almeno un record (la password deve essere crittografata con MD5)
  • In alternativa scaricare il file esempio2.sql del tutorial ed importarlo con phpMyAdmin (se non sai come fare vedi il mio tutorial su YouTube)

Scriviamo il codice PHP per il login/logout

Posizioniamoci all'inizio del file login.php e copiamo e incolliamo il codice prelevato dal link 2 quindi effettuare le seguenti modifiche:

<?php
$msg=""; //Gestione messaggio d'errore
if (isset($_POST['email']) && isset($_POST['password'])) {
    //Recupero dati dal form
    $user = $_POST['email'];
    $pw = $_POST['password'];
    $pw_md5= md5($pw);
    //Accesso al database
    $servername = "localhost";
    $username = "root";
    $password = "";
    $dbname = "esempio2";

// Create connection
    $conn = new mysqli($servername, $username, $password, $dbname);
// Check connection
    if ($conn->connect_error) {
        die("Connection failed: " . $conn->connect_error);
    }
    $sql = "SELECT * FROM utenti WHERE username='$user' AND password='$pw_md5'";
    $result = $conn->query($sql);
    if ($result->num_rows > 0) {
        // Attivo la sessione
        session_start();
        $_SESSION['datiUtente']=$result->fetch_assoc();
        $_SESSION['login']=TRUE;
        header("location: dashboard.php");   
    } else {
        //echo "0 results";
        $msg="Nome utente o password errati";
    }
    $conn->close();
}
?>

Proviamo se funziona il login!

Inseriamo prima delle credenziali errate e vediamo che cosa risponde il sistema. Dopo proviamo ad inserire le credenziali corrette (se avete utilizzato il database del tutorial)

Username: Questo indirizzo email è protetto dagli spambots. È necessario abilitare JavaScript per vederlo.

Password: mario

Se tutto funziona dovremmo essere indirizzati alla pagina Dashboard (file dashboard.php).

Si può anche verificare se è stata creato il cookie di sessione: da Chrome premere F12, selezionare la scheda Application; Dovreste trovare un cookie di nome PHPSESSID. Se c'è vuol dire che la sessione è stata creata!

 

 Scriviamo il codice PHP per il logout

Creiamo un nuovo file di nome logout.php e copiamoci dentro il codice prelevato al link 3 ed aggiungiamo il comando di re-indirizzamento: header("location: index.php");

<?php
// remove all session variables
session_unset();
// destroy the session
session_destroy();
//Reindirizza alla home page
header("location: index.php");
?>

 

 Proteggiamo la Dashboard da accessi non autorizzati ed attiviamo il link per il logout

Posizioniamoci all'inizio del file dashboard.php ed aggiungiamo le seguenti righe di codice PHP:

<?php
session_start();
if(!isset($_SESSION['login']))header("location: login.php"); //Accesso riservato agli uteti autenticati
?>

Se la variabile di sessione non esiste (quindi l'utente non è loggato!) si viene re-indirizzati alla pagina di login

Modifichiamo la riga del link "Sign Out" così: <a class="nav-link" href='logout.php'>Sign out</a>

Ricaricate la pagina e verificate che il tutto funzioni. Provate un ciclo completo:

Home page-->Login-->Dashboard-->Home Page

Bene il nostro tutorial finisce qui.

Guarda il video tutorial

Il codice del tutorial

il file index.php

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta name="description" content="">
    <meta name="author" content="">
    <link rel="icon" href='favicon.ico'>

    <title>ClaudioShop|Home</title>

    <!-- Bootstrap core CSS -->
    <link href='dist/css/bootstrap.min.css' rel="stylesheet">

    <!-- Custom styles for this template -->
    <link href='sticky-footer-navbar.css' rel="stylesheet">
  </head>

  <body>

    <header>
      <!-- Fixed navbar -->
      <nav class="navbar navbar-expand-md navbar-dark fixed-top bg-dark">
        <a class="navbar-brand" href="#">Fixed navbar</a>
        <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarCollapse" aria-controls="navbarCollapse" aria-expanded="false" aria-label="Toggle navigation">
          <span class="navbar-toggler-icon"></span>
        </button>
        <div class="collapse navbar-collapse" id="navbarCollapse">
          <ul class="navbar-nav mr-auto">
            <li class="nav-item active">
              <a class="nav-link" href="#">Home <span class="sr-only">(current)</span></a>
            </li>
            <li class="nav-item">
              <a class="nav-link" href='login.php'>Login</a>
            </li>
            <li class="nav-item">
              <a class="nav-link disabled" href="#">Disabled</a>
            </li>
          </ul>
          <form class="form-inline mt-2 mt-md-0">
            <input class="form-control mr-sm-2" type="text" placeholder="Search" aria-label="Search">
            <button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button>
          </form>
        </div>
      </nav>
    </header>

    <!-- Begin page content -->
    <main role="main" class="container">
      <h1 class="mt-5">Benvenuti da Claudio Shop E-Commerce</h1>
      <p class="lead">Pin a fixed-height footer to the bottom of the viewport in desktop browsers with this custom HTML and CSS. A fixed navbar has been added with <code>padding-top: 60px;</code> on the <code>body &gt; .container</code>.</p>
      <p>Back to <a href="/jm/../sticky-footer">the default sticky footer</a> minus the navbar.</p>
    </main>

    <footer class="footer">
      <div class="container">
        <span class="text-muted">Realizzato da Vincent</span>
      </div>
    </footer>

    <!-- Bootstrap core JavaScript
    ================================================== -->
    <!-- Placed at the end of the document so the pages load faster -->
    <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
    <script>window.jQuery || document.write('<script src="/jm/assets/js/vendor/jquery-slim.min.js"><\/script>')</script>
    <script src='assets/js/vendor/popper.min.js'></script>
    <script src='dist/js/bootstrap.min.js'></script>
  </body>
</html>

 

Il file login.php

<?php
$msg=""; //Gestione messaggio d'errore
if (isset($_POST['email']) && isset($_POST['password'])) {
    //Recupero dati dal form
    $user = $_POST['email'];
    $pw = $_POST['password'];
    $pw_md5= md5($pw);
    //Accesso al database
    $servername = "localhost";
    $username = "root";
    $password = "";
    $dbname = "esempio2";

// Create connection
    $conn = new mysqli($servername, $username, $password, $dbname);
// Check connection
    if ($conn->connect_error) {
        die("Connection failed: " . $conn->connect_error);
    }
    $sql = "SELECT * FROM utenti WHERE username='$user' AND password='$pw_md5'";
    $result = $conn->query($sql);
    if ($result->num_rows > 0) {
        // Attivo la sessione
        session_start();
        $_SESSION['datiUtente']=$result->fetch_assoc();
        $_SESSION['login']=TRUE;
        header("location: dashboard.php");   
    } else {
        //echo "0 results";
        $msg="Nome utente o password errati";
    }
    $conn->close();
}
?>

<!doctype html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
        <meta name="description" content="">
        <meta name="author" content="">
        <link rel="icon" href='favicon.ico'>

        <title>Signin Template for Bootstrap</title>

        <!-- Bootstrap core CSS -->
        <link href='dist/css/bootstrap.min.css' rel="stylesheet">

        <!-- Custom styles for this template -->
        <link href='signin.css' rel="stylesheet">
    </head>

    <body class="text-center">
        <form class="form-signin" method="post" action="login.php">
            <img class="mb-4" src="https://getbootstrap.com/assets/brand/bootstrap-solid.svg" alt="" width="72" height="72">
            <h1 class="h3 mb-3 font-weight-normal">Please sign in</h1>
            <label for="inputEmail" class="sr-only">Email address</label>
            <input type="email" name="email" id="inputEmail" class="form-control" placeholder="Email address" required autofocus>
            <label for="inputPassword" class="sr-only">Password</label>
            <input type="password" name="password" id="inputPassword" class="form-control" placeholder="Password" required>
            <div class="checkbox mb-3">
                <label>
                    <?php print $msg; ?>                  
                </label>
            </div>
            <button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
            <p class="mt-5 mb-3 text-muted">&copy; 2017-2018</p>
        </form>
    </body>
</html>

 

Il file dashboard.php

<?php
session_start();
if(!isset($_SESSION['login']))header("location: login.php"); //Accesso riservato agli uteti autenticati
?>

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta name="description" content="">
    <meta name="author" content="">
    <link rel="icon" href='favicon.ico'>

    <title>Dashboard Template for Bootstrap</title>

    <!-- Bootstrap core CSS -->
    <link href='dist/css/bootstrap.min.css' rel="stylesheet">

    <!-- Custom styles for this template -->
    <link href='dashboard.css' rel="stylesheet">
  </head>

  <body>
    <nav class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0">
      <a class="navbar-brand col-sm-3 col-md-2 mr-0" href="#">Company name</a>
      <input class="form-control form-control-dark w-100" type="text" placeholder="Search" aria-label="Search">
      <ul class="navbar-nav px-3">
        <li class="nav-item text-nowrap">
          <a class="nav-link" href='logout.php'>Sign out</a>
        </li>
      </ul>
    </nav>

    <div class="container-fluid">
      <div class="row">
        <nav class="col-md-2 d-none d-md-block bg-light sidebar">
          <div class="sidebar-sticky">
            <ul class="nav flex-column">
              <li class="nav-item">
                <a class="nav-link active" href="#">
                  <span data-feather="home"></span>
                  Dashboard <span class="sr-only">(current)</span>
                </a>
              </li>
              <li class="nav-item">
                <a class="nav-link" href="#">
                  <span data-feather="file"></span>
                  Orders
                </a>
              </li>
              <li class="nav-item">
                <a class="nav-link" href="#">
                  <span data-feather="shopping-cart"></span>
                  Products
                </a>
              </li>
              <li class="nav-item">
                <a class="nav-link" href="#">
                  <span data-feather="users"></span>
                  Customers
                </a>
              </li>
              <li class="nav-item">
                <a class="nav-link" href="#">
                  <span data-feather="bar-chart-2"></span>
                  Reports
                </a>
              </li>
              <li class="nav-item">
                <a class="nav-link" href="#">
                  <span data-feather="layers"></span>
                  Integrations
                </a>
              </li>
            </ul>

            <h6 class="sidebar-heading d-flex justify-content-between align-items-center px-3 mt-4 mb-1 text-muted">
              <span>Saved reports</span>
              <a class="d-flex align-items-center text-muted" href="#">
                <span data-feather="plus-circle"></span>
              </a>
            </h6>
            <ul class="nav flex-column mb-2">
              <li class="nav-item">
                <a class="nav-link" href="#">
                  <span data-feather="file-text"></span>
                  Current month
                </a>
              </li>
              <li class="nav-item">
                <a class="nav-link" href="#">
                  <span data-feather="file-text"></span>
                  Last quarter
                </a>
              </li>
              <li class="nav-item">
                <a class="nav-link" href="#">
                  <span data-feather="file-text"></span>
                  Social engagement
                </a>
              </li>
              <li class="nav-item">
                <a class="nav-link" href="#">
                  <span data-feather="file-text"></span>
                  Year-end sale
                </a>
              </li>
            </ul>
          </div>
        </nav>

        <main role="main" class="col-md-9 ml-sm-auto col-lg-10 pt-3 px-4">
          <div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
            <h1 class="h2">Dashboard</h1>
            <div class="btn-toolbar mb-2 mb-md-0">
              <div class="btn-group mr-2">
                <button class="btn btn-sm btn-outline-secondary">Share</button>
                <button class="btn btn-sm btn-outline-secondary">Export</button>
              </div>
              <button class="btn btn-sm btn-outline-secondary dropdown-toggle">
                <span data-feather="calendar"></span>
                This week
              </button>
            </div>
          </div>

          <canvas class="my-4" id="myChart" width="900" height="380"></canvas>

          <h2>Section title</h2>
          <div class="table-responsive">
            <table class="table table-striped table-sm">
              <thead>
                <tr>
                  <th>#</th>
                  <th>Header</th>
                  <th>Header</th>
                  <th>Header</th>
                  <th>Header</th>
                </tr>
              </thead>
              <tbody>
                <tr>
                  <td>1,001</td>
                  <td>Lorem</td>
                  <td>ipsum</td>
                  <td>dolor</td>
                  <td>sit</td>
                </tr>
                <tr>
                  <td>1,002</td>
                  <td>amet</td>
                  <td>consectetur</td>
                  <td>adipiscing</td>
                  <td>elit</td>
                </tr>
                <tr>
                  <td>1,003</td>
                  <td>Integer</td>
                  <td>nec</td>
                  <td>odio</td>
                  <td>Praesent</td>
                </tr>
                <tr>
                  <td>1,003</td>
                  <td>libero</td>
                  <td>Sed</td>
                  <td>cursus</td>
                  <td>ante</td>
                </tr>
                <tr>
                  <td>1,004</td>
                  <td>dapibus</td>
                  <td>diam</td>
                  <td>Sed</td>
                  <td>nisi</td>
                </tr>
                <tr>
                  <td>1,005</td>
                  <td>Nulla</td>
                  <td>quis</td>
                  <td>sem</td>
                  <td>at</td>
                </tr>
                <tr>
                  <td>1,006</td>
                  <td>nibh</td>
                  <td>elementum</td>
                  <td>imperdiet</td>
                  <td>Duis</td>
                </tr>
                <tr>
                  <td>1,007</td>
                  <td>sagittis</td>
                  <td>ipsum</td>
                  <td>Praesent</td>
                  <td>mauris</td>
                </tr>
                <tr>
                  <td>1,008</td>
                  <td>Fusce</td>
                  <td>nec</td>
                  <td>tellus</td>
                  <td>sed</td>
                </tr>
                <tr>
                  <td>1,009</td>
                  <td>augue</td>
                  <td>semper</td>
                  <td>porta</td>
                  <td>Mauris</td>
                </tr>
                <tr>
                  <td>1,010</td>
                  <td>massa</td>
                  <td>Vestibulum</td>
                  <td>lacinia</td>
                  <td>arcu</td>
                </tr>
                <tr>
                  <td>1,011</td>
                  <td>eget</td>
                  <td>nulla</td>
                  <td>Class</td>
                  <td>aptent</td>
                </tr>
                <tr>
                  <td>1,012</td>
                  <td>taciti</td>
                  <td>sociosqu</td>
                  <td>ad</td>
                  <td>litora</td>
                </tr>
                <tr>
                  <td>1,013</td>
                  <td>torquent</td>
                  <td>per</td>
                  <td>conubia</td>
                  <td>nostra</td>
                </tr>
                <tr>
                  <td>1,014</td>
                  <td>per</td>
                  <td>inceptos</td>
                  <td>himenaeos</td>
                  <td>Curabitur</td>
                </tr>
                <tr>
                  <td>1,015</td>
                  <td>sodales</td>
                  <td>ligula</td>
                  <td>in</td>
                  <td>libero</td>
                </tr>
              </tbody>
            </table>
          </div>
        </main>
      </div>
    </div>

    <!-- Bootstrap core JavaScript
    ================================================== -->
    <!-- Placed at the end of the document so the pages load faster -->
    <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
    <script>window.jQuery || document.write('<script src="/jm/../../../../assets/js/vendor/jquery-slim.min.js"><\/script>')</script>
    <script src='assets/js/vendor/popper.min.js'></script>
    <script src='dist/js/bootstrap.min.js'></script>

    <!-- Icons -->
    <script src="https://unpkg.com/feather-icons/dist/feather.min.js"></script>
    <script>
      feather.replace()
    </script>

    <!-- Graphs -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.1/Chart.min.js"></script>
    <script>
      var ctx = document.getElementById("myChart");
      var myChart = new Chart(ctx, {
        type: 'line',
        data: {
          labels: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
          datasets: [{
            data: [15339, 21345, 18483, 24003, 23489, 24092, 12034],
            lineTension: 0,
            backgroundColor: 'transparent',
            borderColor: '#007bff',
            borderWidth: 4,
            pointBackgroundColor: '#007bff'
          }]
        },
        options: {
          scales: {
            yAxes: [{
              ticks: {
                beginAtZero: false
              }
            }]
          },
          legend: {
            display: false,
          }
        }
      });
    </script>
  </body>
</html>

 

Il file esempio2.sql

 

-- phpMyAdmin SQL Dump
-- version 4.7.4
-- https://www.phpmyadmin.net/
--
-- Host: 127.0.0.1
-- Creato il: Mag 23, 2020 alle 11:40
-- Versione del server: 10.1.30-MariaDB
-- Versione PHP: 7.2.1

SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
SET AUTOCOMMIT = 0;
START TRANSACTION;
SET time_zone = "+00:00";


/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8mb4 */;

--
-- Database: `esempio2`
--
CREATE DATABASE IF NOT EXISTS `esempio2` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
USE `esempio2`;

-- --------------------------------------------------------

--
-- Struttura della tabella `utenti`
--

CREATE TABLE `utenti` (
  `id` int(11) NOT NULL,
  `nome` varchar(60) NOT NULL,
  `cognome` varchar(50) NOT NULL,
  `username` varchar(100) NOT NULL,
  `password` varchar(128) NOT NULL,
  `data_registrazione` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

--
-- Dump dei dati per la tabella `utenti`
--

INSERT INTO `utenti` (`id`, `nome`, `cognome`, `username`, `password`, `data_registrazione`) VALUES
(1, 'Mario', 'Rossi', Questo indirizzo email è protetto dagli spambots. È necessario abilitare JavaScript per vederlo.', 'de2f15d014d40b93578d255e6221fd60', '2020-04-03 13:46:30'),
(2, 'Eva', 'Kant', Questo indirizzo email è protetto dagli spambots. È necessario abilitare JavaScript per vederlo.', '14bd76e02198410c078ab65227ea0794', '2020-04-03 13:46:30');

--
-- Indici per le tabelle scaricate
--

--
-- Indici per le tabelle `utenti`
--
ALTER TABLE `utenti`
  ADD PRIMARY KEY (`id`);

--
-- AUTO_INCREMENT per le tabelle scaricate
--

--
-- AUTO_INCREMENT per la tabella `utenti`
--
ALTER TABLE `utenti`
  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=3;
COMMIT;

/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;

Allegati Articolo 

* Database

* Esempi Boostrap4

* Il progetto completo realizzato con NetBeans IDE

* Demo