|
|
Inleiding |
|
Dit hoofdstuk gaat over sessies en autorisatie. Autorisatie is erg belangrijk in webapplicaties. Het is bijvoorbeeld erg prettig als alleen jij bij je Facebook account gegevens kunt wijzigen of, nog meer prive, alleen jij in een bankapplicatie geld kan overmaken vanuit jouw bankrekening. Je moet je in deze gevallen dus aanmelden met een username en wachtwoord. Dit alles liefst in een versleutelde omgeving (https) en met een alleen bij jou bekend password. In dit hoofdstuk voldoen we aan deze voorwaarden niet. Websrv201 is niet als htrps server ingericht en om het leven voor jou als programmeur iets eenvoudiger te laten zijn versleutelen we de wachtwoorden in de voorbeelden nog niet. Sessies en autorisatie hebben dus iets te maken met de afhandeling van een reeks van acties van gebruikers en toegang van gebruikers tot websites. Sessies in php zijn al aan bod gekomen in de cursus Opdracht PHP H4/V5 hoofdstuk 8. Heb je dat hoofdstuk niet gedaan dan is het noodzakelijk dat je dat deel eerst doorneemt. Aan het einde van dit hoofdstuk weet je :
|
|
|
|
Introductie sessie |
|
We herhalen hier kort de betekenis van sessies. In een dagelijkse situatie heb je misschien wel meegemaakt dat je bij een aanvraag bij een loket een nummer kreeg toegewezen. Met dat nummer kon je verder de procedure in totdat je aanvraag was afgerond. Daarna gooide je je nummer weg. Binnen websites kunnen we dit principe ook gebruiken. Je logt in om bijvoorbeeld een bestelling uit te voeren, dan is het handig als de volgende pagina (ook nog weet) dat jij als gebruiker de bestelling plaatst. PhP kan zo'n nummertje uitdelen in de vorm van sessies. Een sessie slaat dus tijdelijk bepaalde gegevens op bij de webserver (waar de website wordt gehost) en zal (als het goed is) aan het einde van de rit worden weggegooid. Het is belangrijk dat sessies goed staan ingesteld om te voorkomen dat ze na enkele uren nog steeds bestaan of dat een andere gebruiker jouw bestelling of andere gegevens kan lezen. In het voorbeeld hiernaast (voorbeeld 5 uit Opdracht PHP H4/V5 hoofdstuk 8) wordt in één document een sessie aangemaakt. Kun je één gebruikers actie doen en kun je de sessie afsluiten. In het voorbeeld wordt een array gebruikt om tijdelijk gegevens op te slaan. Deze aanpak moet je ook gaan gebruiken voor het vullen van een winkelwagen. De code van het voorbeeld staat hieronder. |
|
Opdrachten |
|
sessie |
<?php //opslaan als sessie.php function voegToe(&$naam,&$positieve,&$verbeterpunt) { $result=""; if(isset($_POST['naam']) && !empty($_POST['naam']) ) { $naam=trim($_POST['naam']); $verbeterpunt=""; $positieve=""; if(isset($_POST['verbeterpunt']) && !empty($_POST['verbeterpunt']) ) { $verbeterpunt=trim($_POST['verbeterpunt']); } if(isset($_POST['positieve']) && !empty($_POST['positieve']) ) { $positieve=trim($_POST['positieve']); } $_SESSION['eigenschappen'][$naam]=array($positieve,$verbeterpunt); } $result="<table>"; $result.="<tr><td>Naam</td><td>Positieve eigenschap</td><td>Verbeterpunt</td></tr>"; foreach( $_SESSION['eigenschappen'] as $key => $value ) { $result.="<tr><td>$key</td><td>{$value[0]}</td><td>{$value[1]}</td></tr>"; } $result.="</table>"; return $result; } $naam=""; $positieve=""; $verbeterpunt=""; $uitvoer=""; $actie=""; $status=""; session_start(); // sessie starten //We testen of een door ons gemaakte sessie nog niet bestaat if(!isset($_SESSION['mijnid']) ) { $sessionid= $_SESSION['mijnid'] = session_id(); // uniek nummer genereren $_SESSION['eigenschappen']=array(); $uitvoer.= "Sessie gegenereerd.<br/>"; $status="gestart"; } if(isset($_POST['actie'])) { $actie =$_POST['actie']; } switch($actie) { case "Stop": // session_unset(); $uitvoer.="Stop: Ik ga stoppen gestopt met sessie:". $_SESSION['mijnid'].":<br/>";session_destroy(); $uitvoer.="! Daarmee worden alle personen gewist!"; break; case "Voeg toe": $uitvoer.= voegToe($naam,$positieve,$verbeterpunt); break; } echo <<<END <!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <title>Page title</title> </head> <body> <h1>Mijn sessie applicatie: Overzicht eigenschappen van mijn vrienden:</h1> <form action="{$_SERVER['PHP_SELF']}" method="post"> <table summary=""> <tr> <td>Geef een naam:</td> <td><input name="naam" value="$naam"/></td> </tr> <tr> <td>Geef een positieve eigenschap:</td> <td><input name="positieve" value="$positieve"/></td> </tr> <tr> <td>Geef een verbeterpunt:</td> <td><input name="verbeterpunt" value="$verbeterpunt"/></td> </tr> <tr> <td colspan=2 ><input type="submit" name="actie" value="Voeg toe"/> <input type="submit" name="actie" value="Stop"/> </td> </tr> </form> <p>Overzicht eigenschappen</p> $uitvoer </body> </html> END; ?> |
|
|
autorisatie |
|
We gaan even verder bij de analogie van het loket. Soms moet je je eerst kunnen legitimeren voor je verder mag in de procedure. Kun je je niet legitimeren dan krijg je geen toegang tot de afhandeling. Dit proces noemt men autorisatie. Bij veel websites heb voor bepaalde delen een gebruikersnaam en wachtwoord nodig. De server van de website controleert dan of de gebruikersnaam en wachtwoord geldig zijn. Deze gegevens moeten dan wel ergens zijn opgeslagen. In de database 'garagebedrijf' is zijn in de klanten tabel de velden loginname en password aanwezig. In de code index.php is een voorbeeld aanwezig om acties door klanten te laten uitvoeren pas als ze zijn ingelogd. |
|
Opdrachten |
|
voorbeeld |
<?php // Opslaan als index.php // Start sessie session_start(); //Laad database code require_once("database.php"); //Laad algemene code require_once("algemeen.php"); //Laad code voor de acties met betrekking tot producten die we op de database gaan doen require_once("product.php"); //Laad code voor de acties met betrekking tot autorisatie require_once("autorisatie.php"); // Zorg ervoor dat de bladzijde altijd vanuit de server wordt ververst // Zie https://www.imperva.com/learn/performance/cache-control/ en // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control header("Cache-control: no-store"); // declareer variabelen $menu = ""; $uitvoer=""; $user=""; $password=""; $toegelaten=false; $toegelaten_fout_boodschap=""; $uitvoer=""; $actie=""; // lees de actie in if( isset($_POST['actie']) && !empty($_POST['actie']) ) { $actie=$_POST['actie']; } // test of user als is ingelogd // Voeg hier eigen commentaar toe. if(isset($_SESSION["access"]) && $_SESSION["access"] == "toegelaten" && $_SESSION["rol"] && $_SESSION["rol"] == "medewerker") { $toegelaten=true; $user=$_SESSION["user"]; $menu = getMenu(); // Haal het menu door de functie getMenu() uit acties.php op te roepen } else // zo niet dan komt de bezoeker mogelijkerwijs van het inlog scherm. { // Voeg hier eigen commentaar toe. if($actie=="Log in" && checkLogin() ) { $menu = getMenu(); } $uitvoer= "<h2>$toegelaten_fout_boodschap.</h2>"; } // Als je bent toegelaten toon je de hoofdbladzijde anders // toon je het inlogscherm if($toegelaten) { // Als ingelogd persoon kun je de volgende acties uitvoeren switch($actie) { case "Afmelden": afmelden(); $uitvoer = getLoginScreen(); $menu=""; break; case "Toon info": $uitvoer=tooninfo(); break; case "verwijder": $uitvoer=toonArtikelVerwijderTabel(true); // Voer de functie toonArtikelVerwijderTabel() in acties.php uit break; case "Bevestig Verwijderen": $uitvoer=productVerwijderen(); // Voer de functie ProductWijzigen() in acties.php uit break; case "wijzig": // Voer de functie toonArtikelWijzigTabel met 4 nu nog lege fouten in acties.php uit $uitvoer=toonArtikelWijzigTabel(array_fill(0,4,""),true); break; case "Wijziging Doorvoeren": $uitvoer=productWijzigen(); // Voer de functie ProductWijzigen() in acties.php uit break; case "Invoeren": $uitvoer=artikelInvoeren(); // Voer de functie ProductInvoeren() in acties.php uit break; case "Voeg Product Toe": // Voer de functie toonArtikelInvoerTabel() in acties.php uit met 4 lege waarde fout paren $uitvoer=toonArtikelInvoerTabel(legeInvoerEnFout(4),true); break; case "Toon Artikelen": $uitvoer=toonArtikelenLijst(); break; case "Toon VerbindingStatus": $uitvoer = toonVerbindingStatus(); break; default: break; } } else { // Als niet ingelogd persoon kun je de volgende acties uitvoeren switch($actie) { case "Registreren": $uitvoer = "De functionaliteit Registreren moet nog worden gemaakt"; default: $uitvoer .= getLoginScreen(); break; } } echo <<<END <!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>Garagehuis</title> <style type="text/css"> td { border-bottom: 1px groove black; } tr:nth-child(odd) { background-color: lightblue; } </style> </head> <h1>Garagebedrijf</h1> <body> <form action="{$_SERVER['PHP_SELF']}" method="POST"> $menu <hr> $uitvoer </form> </body> </html> END; ?> |
Vervang in algemeen.php de functie getMenu() door de volgende versie
function getMenu() { $uitvoer=<<<END <table class='menu' summary=""> <tr> <td><input type="submit" name="actie" value="Toon Artikelen"> </td> <td><input type="submit" name="actie" value="Voeg Product Toe"> </td> <td><input type="submit" name="actie" value="Afmelden"> </td> <td><input type="submit" name="actie" value="Toon info"> </td> </tr> </table> END; return $uitvoer; } |
|
autorisatie.php |
<?php // Opslaan als autorisatie.php /** * autorisatie.php bevat de code nodig voor het aanmelden bij de applicatie * nodig is code uit database.php */ global $toegelaten_fout_boodschap; global $user; global $password; global $toegelaten; /** * checkLogin is de eerste functie die wordt aangeroepen in het autorisatie proces. * Zijn de formulier gegevens aanwezig dan wordt via de checkUser functie de aanwezigheid van * de gebruiker in de database worden gecontroleerd. */ function checkLogin() { global $toegelaten_fout_boodschap; global $user; global $password; global $toegelaten; $toegelaten=false; /* Haal gebruikersnaam en wachtwoord uit het formulier */ // Voeg hier eigen commentaar toe. if( isset($_POST['loginname']) && !empty($_POST['loginname']) ) { $user = $_POST['loginname']; if( isset($_POST['password']) && !empty($_POST['password']) ) { $password = $_POST['password']; // Voeg hier eigen commentaar toe. if($toegelaten=checkUser($user,$password)) { /* toegang is verkregen */ $toegelaten_fout_boodschap = "$user, welkom bij mijn webapplicatie"; } else { /* toegang geweigerd */ afmelden(); } } } return $toegelaten; } /** * checkUser: test of de gebruiker en zijn wachtwoord bestaan. * Zo niet laat het inlog scherm weer zien anders krijg je toegang * NB: in garagebedrijfnieuwenhuis voorbeeld is bij de klanten het * wachtwoord ingesteld op "123<Achternaam>" */ function checkUser($user,$password) { global $toegelaten_fout_boodschap; $toegelaten=false; $melding=""; // initialisatie van variabele om connectie foutmelding in te plaatsen global $db; // Haal een verwijzing naar de huidige connectie in database.php //verbinding maken met database if(!$db) maakVerbinding($db,$melding); if ($db) { try { $query = "SELECT id,loginname,password FROM medewerker ". " WHERE loginname = :user AND password = :password"; $opdracht = $db->prepare($query); $opdracht->bindParam(':user', $user); $opdracht->bindParam(':password', $password); $opdracht->execute(); list($id,$loginname,$password) = $opdracht->fetch(PDO::FETCH_NUM); if(!empty($id)) { $toegelaten_fout_boodschap= "Toegang verkregen: Welkom, $user!"; $toegelaten=true; // Voeg hier eigen commentaar toe. $_SESSION["access"] = "toegelaten"; $_SESSION["user"] = $user; $_SESSION["medewerkernummer"] = $id; $_SESSION["rol"] = "medewerker"; } else { $toegelaten_fout_boodschap .= "Toegang gewijgerd: Probeer het nogmaals."; } } catch(PDOException $e) // Er is een fout opgetreden in SQL { $toegelaten_fout_boodschap .= "Fout in query"; } verbreekVerbinding(); } else { $toegelaten_fout_boodschap= "interne fout: Probeer in contact te komen met het beheer van deze site!"; } return $toegelaten; } /** * afmelden: functie die moet worden aangeroepen als je wil afmelden. */ function afmelden() { // Maak de Sessions variabele op de server leegleeg $_SESSION = array(); // ruim alles op bij de client session_destroy(); } /** * tooninfo: functie toont de gegevens van de gebruiker. */ function tooninfo() { $uitvoer=""; $melding=""; // initialisatie van variabele om connectie foutmelding in te plaatsen global $toegelaten_fout_boodschap; global $db; // Haal een verwijzing naar de huidige connectie in database.php //verbinding maken met database if(!$db) maakVerbinding($db,$melding); if ($db) { /* SQL statement to query the database */ // Voeg hier eigen commentaar toe. try { $medewerkernummer = $_SESSION["medewerkernummer"]; $query = "SELECT * FROM medewerker WHERE id=:medewerkernummer"; $opdracht = $db->prepare($query); $opdracht->bindParam(':medewerkernummer', $medewerkernummer); $opdracht->execute(); list($id,$loginname,$password,$voornaam, $achternaam,$straat,$huisnummer, $postcode,$woonplaats) = $opdracht->fetch(PDO::FETCH_NUM); $uitvoer .= "Jij bent $voornaam $achternaam en woont op $straat in $woonplaats.<br/>". "Als gebruikersnaam heb je: $loginname Je password is geheim."; } catch(PDOException $e) // Er is een fout opgetreden in SQL { $uitvoer .= "Fout uitvoeren query! $query"; } verbreekVerbinding(); } else { $uitvoer.= "interne fout: Probeer in contact te komen met het beheer van deze site!". mysql_error($db); } return $uitvoer; } /** * getLoginScreen: geeft de html code voor het inlogscherm. */ function getLoginScreen() { global $toegelaten_fout_boodschap; global $user; $uitvoer=<<<END <h1>Login in mijn applicatie</h1> <form action="{$_SERVER['PHP_SELF']}" method="post"> <label for="loginname">Login naam</label> <input type="text" name="loginname" id="loginname" value="$user"/> <br /> <label for="password">Password</label> <input type="password" name="password" id="password" /> <br /> <input type="submit" name="actie" value="Log in" /> </form> END; return $uitvoer; } //einde van het PhP blok ?> |
|
|
Opdracht webwinkel |
Er zijn heel veel kant en klare webwinkel applicaties bijvoorbeeld binnen de Bitnami tools. Een zoektocht op duckduckgo met beste gratis webshop software levert ook genoeg keuzes. Wij willen echter dat voor je een groot pakket pakt eerst leert nadenken over de onderdelen die je in zo'n webwinkel moet implementeren. Daarom gaan jullie in groepsverband een klanten en een administratie website maken met behulp van het geleerde hierboven. Ook een andere eigen webapplicatie met database ondersteuning is natuurlijk mogelijk. Een beginnetje vind je hier. |