Het Wiel Uitgevonden:Superglobals
--Taco 21 mrt 2009 01:43 (CET)
In deze tutorial neem ik aan dat je de basis programmeer-structuur van PHP kent. Zo niet, worstel je even door Het Wiel Uitgevonden:Hello World in PHP. Zo wel, dan voel je je vast een beetje bedrogen: PHP zou interactief en dynamisch zijn. Tot nu toe was het alleen een lastige manier om zinloze dingen te doen. Enter superglobals!
Inhoud |
Wat zijn superglobals?
Wanneer een gebruiker een webpagina van je opent, stuurt zijn browser een verzoek naar je server. In dat verzoek staat welk bestand hij wil hebben. Maar er wordt nog meer informatie verzonden: Er kan nog meer in de URL staan, er kan informatie uit een formuliertje zijn meegezonden, misschien een geüpload bestand, cookies, informatie over je besturingssysteem, noem maar op. Al deze informatie wordt door de server verwerkt en onthouden. Vervolgens kan je in PHP deze info weer uitlezen uit, jawel, superglobals.
Veiligheid
Vóór we aan de slag gaan, wil ik nog iets benadrukken. Bijna alle data komt van de gebruiker. En de gebruiker, die vertrouwen we natuurlijk niet! Alle gegevens die gebruikers opsturen, zijn per definitie verdacht. Dus vóór je er iets mee doet, moet je jezelf afvragen of het kwaad kan als er verkeerde dingen in staan. Dus als je het gebruikt in SQL, let op SQLInjectie. Als je het gebruikt in je HTML, gebruik htmlspecialchars(). Wees paranoïde!
Omdat veel beginnende gebruikers dit vergaten, heeft PHP een red-de-onwetenden-optie ingebouwd. Erger nog, ze hebben hem standaard aangezet. Deze heet MagicQuotes. Helemaal gratis verpest PHP je data, door slashes (\) voor enkele en dubbele aanhalingstekens te zetten. Dit helpt in sommige gevallen, maar is nooit afdoende, In PHP 6 stoppen ze daar gelukkig weer mee, maar tot die tijd moet je dus je data redden door die zinloze slashes weer weg te halen. Lees er meer over in MagicQuotes.
Meestgebruikte superglobals
Laten we de belangrijkste even langslopen! Voor een volledige lijst kan je de manual erbij pakken.
$_GET
Een URL bestaat uit verschillende delen. De eerste paar (scheme, host, port, user, pass en path) zijn allemaal bedoeld om een bestand aan te wijzen. Daarna kan er een vraagteken staan, met daarachter data. Tenslotte kan er nog een hekje (#) met een locatie op de pagina staan. Wat ik net 'data' noemde, komt in de $_GET-array terecht. Om het in actie te zien, maak een bestand superglobals.php en plak deze code erin:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Superglobals - GET</title> </head> <body> <ol> <li><a href="superglobals.php">Geen data meesturen</a></li> <li><a href="superglobals.php?naam=Taco">Een naam meesturen</a></li> <li><a href="superglobals.php?id=12">Een id meesturen</a></li> <li><a href="superglobals.php?action=save&website=PFZ&difficulty=drops%20with">Meerdere variabelen meesturen</a></li> </ol> Inhoud van $_GET: <pre> <?php // Laat gewoon de hele array zien, zonder er verder acties aan te hangen print htmlspecialchars(print_r($_GET,true)); ?> </pre> </body> </html>
Je zal de $_GET-array vaak gebruiken in combinatie met primairy keys van tabellen. Denk aan links als
- article.php?article_id=123
- user.php?user_id=456
- forum.php?thread_id=789&mode=print
$_POST
In HTML heb je de mogelijkheid formulieren te maken. Dit varieert van een simpel login-formpje met gebruikersnaam en wachtwoord tot een onaangename meterslange enquete. Nu kan in principe deze info via de GET of de POST worden verstuurd. Kies je de GET-methode, dan wordt het in de URL gecodeerd zoals hierboven. Probleem is dat de URL maar een beperkte lengte kan hebben, ergens rond de 2000-4000. Daarna wordt het meestal afgekapt. Netter is de POST-methode, waarbij de informatie los wordt verzonden. En het zal je niet verbazen dat deze gegevens terug te vinden zijn in de $_POST-array... Voorbeeldtijd!
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Superglobals - POST</title> </head> <body> <a href="superglobals.php">Refresh</a> <form action="superglobals.php" method="post"> Voornaam: <input type="text" name="voornaam" /><br /> Onthouden: <input type="checkbox" name="onthouden" /><br /> Radio1: <input type="radio" name="zender" value="radio_optie_1" /><br /> Radio2: <input type="radio" name="zender" value="radio_optie_2" /><br /> <input type="submit" name="command" value="Versturen die hap!" /><br /> </form> <pre><?php print '$_POST = ' . htmlspecialchars(print_r($_POST,true)); print '$_SERVER[\'REQUEST_METHOD\'] = ' . htmlspecialchars(print_r($_SERVER['REQUEST_METHOD'],true)); ?></pre> </body> </html>
Zoals je kunt zien, is $_SERVER['REQUEST_METHOD'] een handige manier om te controleren of er een formulier is meegezonden. Laad je niet verleiden om te controleren of een submit-waarde is meegestuurd, want dat werkt niet altijd en in alle browsers.
Als je nu eens waardes invult met een ' of een " erin, zie je gelijk of de MagicQuotes aanstaan.
$_FILES
Wordt gebruikt voor het uploaden van files vanuit een form.
nader uit te werken en met voorbeeld te versieren.
$_SERVER
In deze array staan allerlei waardes van de server en de gebruiker. Wat er precies wel en niet instaat, hangt af van je server. Veelgebruikte waardes staan hier in het voorbeeld:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Superglobals - SERVER</title> </head> <body> <p> <a href="superglobals.php">Refresh</a><br /> Dacht je dat je anoniem kon surfen? Think again...<br /> <dl> <?php print '<dt>Je IP</dt><dd>' . htmlspecialchars($_SERVER['REMOTE_ADDR']) . '</dd>'; print '<dt>Je geeft de volgende info over je computer</dt><dd>' . htmlspecialchars($_SERVER['HTTP_USER_AGENT']) . '</dd>'; print '<dt>Je kwam via deze pagina op deze site uit</dt><dd>' . htmlspecialchars($_SERVER['HTTP_REFERER']) . '</dd>'; print '<dt>En je server noemt zich zo</dt><dd>' . htmlspecialchars($_SERVER['HTTP_HOST']) . '</dd>'; ?> </dl> Ach, what the heck, hier heb je de hele lijst: <pre><?php print htmlspecialchars(print_r($_SERVER,true)); ?><pre> </p> </body> </html>
$_COOKIE
Een webpagina heeft in principe geen geheugen. Dat maakt het nogal lastig om in te loggen, of een taal in te stellen, etc. Daarom zijn er cookies bedacht. Cookies zijn eigenlijk stukjes data die je opslaat aan de kant van de gebruiker. Als die gebruiker dan een pagina opvraagt, stuurt hij mee wat er nog aan data lokaal is opgeslagen. In het voorbeeld onthouden we de taal van de gebruiker.
<?php // Cookies moeten altijd VOOR alle tekst worden afgehandeld. // Moeten we de taal aanpassen? if ( isset($_GET['taal'] ) ) { // Vertrouw de input niet! Alleen deze twee waardes worden opgeslagen if ( $_GET['taal'] == 'Engels' || $_GET['taal'] == 'Nederlands' ) { // Stel een cookie in die na 24 uur verloopt. setcookie('taal',$_GET['taal'], time()+24*3600); } } else { // Als de cookie nog leeg is, zet de taal op Nederlands if ( !isset($_COOKIE['taal']) ) { // Stel een cookie in die na 24 uur verloopt. setcookie('taal','Nederlands', time()+24*3600); } } ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Superglobals - COOKIE</title> </head> <body> <p> <a href="superglobals.php">Refresh</a><br /> Je hebt als taal <?php echo htmlspecialchars($_COOKIE['taal']) ?> ingesteld<br /> <a href="superglobals.php?taal=Engels">Kies Engels</a><br /> <a href="superglobals.php?taal=Nederlands">Kies Nederlands</a><br /> </p> </body> </html>
Wanneer we deze code testen, valt op dat het in principe wel werkt, maar de taal altijd één stapje achterloopt. Pas als je nog een keertje refresht, klopt de taal weer met wat je hebt ingesteld. Dit komt omdat éérst de $_COOKIE-array wordt gevuld en je daarna pas de cookies in gaat stellen.
Dit is blijkbaar een handige manier om data over de gebruiker te onthouden. Het kan echter nóg handiger: sessies!
$_SESSION
Het nadeel van cookies is dat de data op de pc van de gebruiker wordt bijgehouden. Als je dus een koekje opslaat dat je 'GebruikerIsIngelogd' noemt, met de waarde 'NeeDatIssieNiet', kan de snoodaard natuurlijk makkelijk van maken 'JaDatIssieWel'. Een veiligere (en makkelijkere) manier is om met sessies te werken. Sessies zitten als volgt in elkaar: Elke gebruiker heeft een unieke, willekeurige en moelijk te raden code. Bijvoorbeeld: l1vg8g7e9jdnnrbh1tqjuunfo0. Dit wordt door PHP vanzelf opgeslagen in een cookie. Dan, bij elke request, opnieuw helemaal vanzelf, stuurt de browser van de gebruiker de code mee naar de server. Die zoekt even in zijn lijstje met codes en besluit 'Oh, die gebruiker ken ik, dat was dinges en dinges en zus en zo'. Tenslotte kan je dan allerlei data opslaan aan de serverkant die gekoppeld is aan die gebruiker. In het voorbeeld 'onthoudt' de server hoe vaak je langs bent gekomen.
<?php // Sessies werken met cookies, dus er mag geen tekst vóór de openings-tag staan session_start(); // Dit is alles. $_SESSION is klaar voor gebruik! $_SESSION['bezoekjes'] = $_SESSION['bezoekjes'] + 1; // $_SESSION is één van de weinige superglobals waar je naar kan schrijven ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Superglobals - SESSION</title> </head> <body> <p> <a href="superglobals.php">Refresh</a><br /> JIJ WEER?? Dat is al de <?php echo $_SESSION['bezoekjes']; ?>e keer! </p> </body> </html>
Het is zo simpel als dat! Eén session_start() aan het begin en je kan per gebruiker informatie bijhouden. Let op dat de informatie weg is zodra hij/zij de browser sluit. Ook is het mogelijk om iemands sessie-code te stelen, dus 100% veilig is het niet. Om het veiliger te maken, kan je bijvoorbeeld iemands IP ook opslaan. We komen hier nog op terug bij Het Wiel Uitgevonden:Inloggen
$_REQUEST is gevaarlijk
In $_REQUEST worden de waarden van $_GET, $_POST en $_COOKIE verzameld. Dat klinkt als een handige variabele omdat je dan geen onderscheid meer hoeft te maken tussen $_GET, $_POST en $_COOKIE, je roept gewoon overal $_REQUEST aan en alles is in orde.
Maar dat is niet zo.
Omdat $_REQUEST de waarden verzamelt kan een waarde uit een $_COOKIE een waarde uit $_GET overschrijven. Als een hacker via Cross-Site-Scripting (XSS) een cookie weet te setten wat jij in $_GET verwacht om b.v. aan te geven welke pagina je wilt tonen, dan kunnen bezoekers bij wie zo'n cookie geset is je site niet meer bezoeken.
Gebruik dus altijd $_GET, $_POST en $_COOKIE apart, en vertrouw $_REQUEST niet!
En nu?
Je hebt geleerd hoe je met de bezoekers van je website kan communiceren. Je kan data versturen in links, forms, cookies, of zonder dat ze het doorhebben via hun browser. De weg ligt nu open om websites te maken, speciaal voor een specifieke gebruiker. Deze kennis gaan we proberen toe te passen in de volgende tutorials van Het Wiel Uitgevonden!==Geen $_REQUEST==





