Bewerkt door vlerknozem op 07-01-2010 20:38
Laten we de stappen eens gaan doornemen.
1. De database
Open phpMyAdmin, en maak indien nodig een nieuwe database aan. Zorg in ieder geval dat je in de juiste database bent. Vervolgens klik je op de knop "SQL" die je links boven ziet. Er opent zich een nieuw venster waar je de volgende code invoegt:
- CREATE TABLE IF NOT EXISTS `gebruikers` (
- `id` int(11) NOT NULL AUTO_INCREMENT,
- `gebruikersnaam` varchar(54) NOT NULL,
- `wachtwoord` varchar(54) NOT NULL,
- PRIMARY KEY (`id`)
- ) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=2 ;
- INSERT INTO `gebruikers` (`id`, `gebruikersnaam`, `wachtwoord`) VALUES
- (1, 'test', 'test');
- CREATE TABLE IF NOT EXISTS `logins` (
- `uid` varchar(54) NOT NULL,
- `sid` varchar(256) NOT NULL,
- `ip` varchar(256) NOT NULL,
- `datum` datetime NOT NULL
- ) ENGINE=MyISAM DEFAULT CHARSET=latin1;
2. Het configuratiebestand
Maak een bestand aan genaamd config.php.
- <?php
- /*
- | Dit is het configuratiebestand van het loginsysteem. Hier worden
- | bepaalde dingen ingesteld die door het gehele loginsysteem gebruikt
- | worden.
- |
- | Gemaakt door Vlerknozem (dit hele loginsysteem eigenlijk!)
- */
- # Een beveiliging om te voorkomen dat men
- # probeert je config.php te openen
- {
- # De bezoeker terug verwijden naar de index
- # En stoppen met PHP uitvoeren, voor de zekerheid
- exit;
- }
- # Een config array aanmaken
- # De mysql host, waar je database op draait. Is meestal localhost
- # De mysql gebruikersnaam. Is meestal niet root
- # Het mysql wachtwoord, is eigenlijk nooit leeg
- # De tabel waar het systeem op draait. Als je de SQL niet hebt uitgevoerd moet je deze aanpassen
- # De login sessie tijd, het aantal uren dat je bent ingelogd dus.
- # MD5 gebruiken om wachtwoorden te coderen? Staat standaard uit
- # Fouten weergeven ? Alleen handig als je aan het testen bent!
- /*
- | De benodigde database velden instellen
- | Elk veld dat je bij het registeren wilt hebben kan je hier toevoegen als nieuwe array waarde.
- | De syntax is: 'veldnaam:flag1|flag2'
- | Het veldnaam en de flags scheid je met dubbele punt. De flags scheid je van elkaar met een verticaal streepje.
- |
- | Flags:
- | verplicht = maak het veld verplicht
- | uniek = De ingevulde waarde voor dit veld mag maar een keer gebruikt worden. (handig voor gebruikersnamen)
- | min=3 = Minimaal in te vullen karakters is in dit geval 3.
- | max=10 = Maximaal in te vullen karakters is in dit geval 10.
- | ==wachtwoord2 = De ingevulde waarde van het huidge veld moet overeen komen met in dit geval de inhoud van het veld 'wachtwoord2'
- | email = Er wordt gecontrolleerd of de ingevulde waarde voldoet aan de eisen van een geldig e-mailadres.
- | md5 = Codeer de ingevulde waarde naar md5.
- */
- ?>
Vul hier de juiste gegevens in. Als je je wachtwoorden als MD5 wilt opslaan, verander dan de variabele 'login_password_md5' naar 'true'.
3. Het login scherm.
Natuurlijk is er een scherm nodig waar men zich kan inloggen. Deze zetten we ook in een apart bestand, en kunnen we later makkelijk includen.
We noemen dit bestand 'login.inc.php'.
- <?php
- if($login->fouten) {
- echo "<p>".$login->fouten."</p>";
- }
- ?>
- <form action="<?php echo $_SERVER['REQUEST_URI']; ?>" method="post">
- <input type="hidden" name="actie" value="login" />
- Gebruikersnaam: <input type="text" name="gebruikersnaam" /><br />
- Wachtwoord: <input type="password" name="wachtwoord" /><br />
- <input type="submit" value="login" />
- </form>
Login fouten worden hier dus ook in weergeven. Let op dat het field "actie" belangrijk is, zodat het systeem weet dat dit het login formulier is. Deze manier is handig bij het gebruik van meerdere formulieren met zelfde veldnamen.
4. De registratie pagina
Met onderstaande code (ik heb het in registreer.php gedaan) kan je gebruikers zich laten registreren. Als je een veld erbij wild dan kan dat. Let op dat je bij in de database ook een veld toevoegd met dezelfde naam als bij name="". Ook onderaan header.php moet je een regel maken bij $login->database_velden, met de juiste instellingen.
- <?php
- /*
- | De registreer pagina waar nieuwe leden zich kunnen registreren.
- | Ook hier is niet zoveel spannends aan de hand
- |
- | We beginnen met de hoofdklasse in te voegen.
- */
- include("loginsysteem/header.php");
- /*
- | Als er fouten zijn (na registreren dan) gaan we die nu tonen.
- */
- if($login->fouten)
- {
- print "<p>".$login->fouten."</p>";
- } else {
- echo 'Je bent succesvol geregistreerd.';
- }
- /*
- | Als er geen fouten zijn dan het formulier
- */
- ?>
- <form method="post" action="">
- <input type="hidden" name="actie" value="registreer_gebruiker" />
- <p>Gebruikersnaam</p>
- <p><input type="text" name="gebruikersnaam" /></p>
- <p>Wachtwoord</p>
- <p><input type="password" name="wachtwoord" /></p>
- <p>Controle wachtwoord</p>
- <p><input type="password" name="wachtwoord2" /></p>
- <p><input type="submit" value="Registreer!" /></p>
- </form>
5. De beveiligde pagina's
Nu moet je alle beveiligde pagina voorzien van het volgende:
- <?php
- include('header.php');
- ?>
- <html>
- <head>
- <title>Test pagina</title>
- </head>
- <body>
- Dit is een voorbeeld pagina. Iedereen
- Hieronder komt een login menu:<br />
- <?php
- if(!$login->get_login_info()) {
- // Niet ingelogd, login deel weergeven
- include('login.inc.php');
- } else {
- ?>
- Welkom <b><?php echo $login->get_login_info('gebruikersnaam');?>!</b><br />
- <a href="index.php?actie=uitloggen">Uitloggen</a>
- <?php
- }
- ?>
- </body>
- </html>
6. Gebruikersinfo opvragen binnen een andere klasse
Hiervoor hoef je natuurlijk geen nieuwe instantie te maken. Doordaad bepaalde data static is, kan je mits de klasse al reeds geladen is, de data overal opvragen. Probeer maar eens met deze code:
- <?php
- echo login::get_login_info('gebruikersnaam');
- ?>
7. Gebruikers info weergeven
Stel je wilt een profiel pagina maken, en je wilt dat er bijvoorbeeld een website url zichtbaar wordt, voeg je in de database gewoon het veld 'website' toe.
Met deze code kan je een veld opvragen:
- <?php
- echo $login->get_login_info('website');
- ?>
Om alles op te vragen:
- <?php
- $info = $login->get_login_info('alles');
- echo $info['gebruikersnaam'] . "<br />";
- echo $info['website'] . "<br />";
- ?>
8. Het header bestand
We gaan een header bestand maken. Deze bevat het hele systeem. Dit bestand noemen we 'header.php'. Hierin hoef je niks te veranderen.
- <?php
- /*
- | Dit is de kern van het hele loginsysteem. Hier gebeurt alles.
- | Dit is een enkele klasse die overal voor zorgt.
- |
- | Eerst een beveiliging (ook gevonden in config.php, zie die file voor
- | verdere uitleg)
- */
- {
- }
- /*
- | Het configuratiebestand laden om verbinding te kunnen maken met de database
- | en om wat andere instellingen te kunnen gebruiken die later nodig zijn.
- */
- include_once("config.php");
- /*
- | Nu beginnen we aan de klasse, dit is een simpele klasse die
- | niets meer en niets minder doet dan waarvoor hij gemaakt is:
- | gebruikersauthenticatie.
- */
- class login
- {
- /*
- | Een variabele om aan te geven of de gberuiker is ingelogd,
- | wat standaard niet is, dus de waarde 'false' krijgt
- */
- private static $loginsessie = false;
- /*
- | Een variabele om fouten in op te slaan die het systeem
- | teruggeeft.
- */
- public $fouten = "";
- /*
- | Een variabele (array) om wat informatie over de gebruikers
- | in op te slaan.
- */
- /*
- | Een variabele om database velden in op te slaan
- */
- /*
- | Een variabele die bijhoud hoeveel pogingen een gebruiker al
- | heeft gemaakt om in te loggen. We beginnen met tellen bij 0
- */
- private $recheck = 0;
- /*
- | Deze functie word aangeroepen bij het laden van de klasse.
- | Hier word de verbinding met de database tot stand gebracht,
- | gecontroleerd of er al een sessie is, en word er afgewacht
- | tot de gebruiker wil uitloggen
- */
- public function __construct()
- {
- /*
- | Verbinding maken met de database. De informatie word uit config.php
- | gehaald om te kunnen verbinden.
- */
- /*
- | Als er fouten zijn en fouten mogen getoond worden dan
- | worden ze nu opgeroepen (en later pas weergegeven!)
- */
- {
- }
- /*
- | Controleren op een login sessie!
- */
- $this->check_session();
- /*
- | De logout actie koppelen aan de end_session functie welke mensen
- | uitlogd.
- */
- {
- $this->end_session();
- }
- }
- /*
- | De init functie. Deze zorgt ervoor dat wanneer de gebruiker inlogt of registreert
- | hij/zij de juiste pagina voor z'n neus krijgt.
- */
- public function init()
- {
- /*
- | Iemand heeft ergens een formulier verzonden wat bij dit loginsysteem hoort
- */
- if($_SERVER['REQUEST_METHOD'] == "POST" && self::$loginsessie === false)
- {
- /*
- | En het 'actie' veld is gezet, tijd voor wat actie.
- */
- {
- /*
- | Om een grote if-else lussen constructie tegen te
- | gaan doen we het in een switch, dat is makeklijker
- | uit te breiden.
- */
- switch($_POST['actie'])
- {
- case "login": $this->controleer_gegevens(); break;
- case "registreer_gebruiker": $this->registreer_gebruiker(); break;
- }
- }
- }
- }
- /*
- | Een functie om het IP-adres van de gebruiker mee te achterhalen
- */
- public function get_ip()
- {
- /*
- | Als PHP gebruikt maakt van $_SERVER,
- | meerdere pogingen doen om het IP te achterhalen
- | en in $realip weg te schrijven.
- */
- {
- {
- $realip = $_SERVER['HTTP_X_FORWARDED_FOR'];
- }
- {
- $realip = $_SERVER['HTTP_CLIENT_IP'];
- }
- else
- {
- $realip = $_SERVER['REMOTE_ADDR'];
- }
- }
- /*
- | Als PHP geen gebruik maakt van $_SERVER
- | moeten we wat anders proberen.
- */
- else
- {
- {
- }
- {
- }
- else
- {
- }
- }
- /*
- | De variabele realip returnen, zodat we die kunnen gebruiken
- */
- return $realip;
- }
- /*
- | Een functie om gebruikers te registreren. Word aangeroepen in init().
- | Het woord 'private' betekent dat je deze functie alleen in deze klasse
- | (dit bestantd) mag aanroepen. Als je dat niet doet krijg je een foutmelding
- */
- private function registreer_gebruiker()
- {
- /*
- | Even kiken of het actie veld gezet is en de waarde correct is
- */
- {
- /*
- | controleren of de database en het formulier hetzelfde zijn.
- */
- {
- if(show_errors == true)
- {
- /*
- | Ik heb de Exception methode van PHP gebruikt voor deze foutmelding. Eerst stond er dit
- | (kun je erin zetten als je dat liever hebt, moet je wel de throw new Exception(...)
- | weghalen!
- |
- | die("FOUT: Geen velden opgegeven");
- */
- throw new Exception("De volgende fout is opgetreden: <strong>geen velden opgegeven</strong>.");
- }
- else
- {
- }
- }
- /*
- | De database velden array uit elkaar trekken en gaan controleren op bepaalde zaken
- | zoals lengte van gebruikersnamen.
- */
- foreach($this->database_velden as $veld)
- {
- /*
- | Het veld item nog verder uit elkaar halen,
- | scheiden op alle dubbele punten.
- */
- /*
- | De veldnaam ophalen
- */
- $veld_naam = $veld[0];
- /*
- | De velden uit het formulier synchroniseren
- | met die uit de database.
- */
- $velden[$veld_naam] = $_POST[$veld_naam];
- /*
- | De veld instellingen ophalen
- */
- /*
- | De veld instellingen verder uit elkaar halen
- | om te gaan controleren op lengtes enz.
- */
- foreach($veld_instellingen as $instelling)
- {
- /*
- | Als de instelling verplicht is, en het veld is leeg.
- */
- {
- $this->fouten .= "<li>Het veld '".$veld_naam."' is verplicht, maar nu is het leeg.</li>";
- }
- /*
- | Als de md5 instelling ingeschakeld is, omzetten naar MD5
- */
- elseif($instelling == 'md5')
- {
- }
- /*
- | Kijken of er een minimum lengte is
- */
- {
- /*
- | En die dan controleren
- */
- {
- $this->fouten .= "<li>Het veld '".$veld_naam."' is te kort</li>";
- }
- }
- /*
- | Kijken of er een maxium lengte is
- */
- {
- /*
- | En die dan controleren
- */
- {
- $this->fouten .= "<li>Het veld '".$veld_naam."' is te lang.</li>";
- }
- }
- /*
- | Kijken of het veld iets moet matchen
- */
- {
- /*
- | Even kijken of het ook matcht.
- */
- {
- $this->fouten .= '<li>Het veld '.$veld_naam.' en '.substr($instelling, 2).' komen niet overeen</li>';
- }
- }
- /*
- | Controleren of het veld uniek moet zijn
- */
- elseif($instelling == 'uniek')
- {
- $q = mysql_query("SELECT ".$veld_naam." FROM gebruikers WHERE ".$veld_naam." = '".mysql_real_escape_string($velden[$veld_naam])."'");
- if(!$q)
- {
- /*
- | Een verkortte if-else lus.
- | (wat te controleren) ? uitkomst van if : uitkomst van else
- */
- (show_errors == true) ? trigger_error("Er is een MySQL fout opgetreden:<br />".mysql_error(), E_USER_ERROR) : $this->fouten .= '<li>Er is een MySQL fout opgetreden</li>';
- }
- else
- {
- /*
- | controleren of het veld al bestaat,
- */
- {
- $this->fouten .= '<li>De inhoud van veld '.$veld_naam.' bestaat al</li>';
- }
- }
- }
- /*
- | Controleren of het veld een email adres is
- */
- elseif($instelling == 'email')
- {
- /*
- | Controleren of het een geldig email adres is.
- */
- if(!eregi("^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,3})$", $velden[$veld_naam]))
- {
- $this->fouten .= '<li>Het email adres is niet correct</li>';
- }
- }
- }
- }
- /*
- | ALs er geen fouten zijn gevonden in het formulier
- | gaan de de benodigde SQL code genereren.
- */
- if(!$this->fouten)
- {
- $SQL = "INSERT INTO gebruikers ";
- $SQL_TMP = '';
- foreach($velden as $naam => $waarde)
- {
- }
- /*
- | De query is gelukt, nu de gebruiker terug bregen naar de index
- */
- {
- }
- /*
- | Anders een fout tonen.
- */
- else
- {
- (show_errors == true) ? trigger_error("Er is een MySQL fout opgetreden:<br />".mysql_error(), E_USER_ERROR) : $this->fouten .= '<li>Er is een MySQL fout opgetreden</li>';
- }
- }
- }
- }
- /*
- | Een functie om de gegeven van de gebruikers die in willen loggen te controleren.
- */
- private function controleer_gegevens()
- {
- /*
- | Het actie veld is gezet en de waarde is ook goed
- */
- {
- /*
- | Even de gebruikersnaam en wachtwoord beveiligen
- | voordat we deze in de database gooien
- */
- /*
- | Als je in config.php hebt ingesteld dat wachtwoorden
- | gecodeerd moeten worden moet MD5, dan doen we dat hier
- */
- if(login_password_md5 === true)
- {
- }
- /*
- | Een query uitvoeren om te kijken of de gebruiker in de database zit
- */
- $query = mysql_query("SELECT * FROM gebruikers WHERE gebruikersnaam = '".$gebruiker."' AND wachtwoord = '".$wachtwoord."'");
- /*
- | Als dat zo is moet de gebruikersinfo array gevuld worden met informatie,
- | en er moet een sessie gestart worden.
- */
- {
- return $this->start_session();
- }
- /*
- | De gebruiker zit niet in de database. Fout laten zien dan maar
- */
- else
- {
- /*
- | Als er een MySQL fout is deze tonen (of niet, ligt aan je config.php)
- | Is dat niet zo, dan is of de gebruikersnaam of het wachtwoord
- | fout.
- */
- {
- (show_errors == true) ? trigger_error("Er is een MySQL fout opgetreden:<br />".mysql_error(), E_USER_ERROR) : $this->fouten = "Er is een MySQL fout opgetreden";
- }
- else
- {
- $this->fouten = "Gebruikersnaam/wachtwoord niet correct.";
- }
- }
- }
- }
- /*
- | Een functie om te kijken of de gebruiker al is ingelogd.
- */
- private function check_session()
- {
- /*
- | kijken of de recheck variabele van daarstraks niet
- | te groot is geworden.
- | Is dat wel zo dan een foutmelding laten zien en
- | 'false' retourneren.
- */
- if($this->recheck >= 3)
- {
- $this->fouten = "Er is een ongeldige sleutel gevonden.";
- return false;
- }
- /*
- | als de cookie (sid) is gezet en NIET leeg is
- | even controleren of de sleutel uit de cookie
- | klopt met die uit de database (als die er
- | al instaat om mee te beginnen)
- |
- | Is dat zo dan word self::$loginsessie waar en
- | word self::$gebruikersinfo['info'] met de juiste
- | velden gevuld
- |
- | Zo niet, dan word $this->recheck een groter
- */
- {
- $query = mysql_query("SELECT * FROM logins WHERE sid = '".$sid."' AND ip = '".$this->get_ip()."'") or die(mysql_error());
- {
- #$f = mysql_fetch_array($query);
- {
- self::$loginsessie = true;
- }
- }
- }
- else
- {
- $secondes = login_session_time * 3600;
- $this->recheck = $this->recheck + 1;
- }
- }
- /*
- | De sessie die hierboven word besproken starten, de correcte informatie
- | in de database opslaan ,een cookie maken en de gebruiker terugleiden
- | naar waar hij/zij vandaan kwam.
- */
- private function start_session()
- {
- $info = self::$gebruikersinfo['info'];
- $SQL = "INSERT INTO logins ";
- $SQL .= ", datum = NOW() ";
- $secondes = login_session_time * 3600;
- }
- /*
- | Een functie om de sessie die hierboven besproken word te stoppen, en de
- | informatie uit de database te halen, de cookie te vernietigen en de
- | gebruiker terug te leiden naar waar hij/zij vandaan kwam.
- */
- private function end_session()
- {
- mysql_query("DELETE FROM logins WHERE sid = '".$_COOKIE['sid']."' AND ip = '".$this->get_ip()."'") or die(mysql_error());
- $secondes = login_session_time * 3600;
- }
- /*
- | De functie om gebruikers informatie op te halen en te controleren
- | of de gebruikers ingelogd is.
- */
- public static function get_login_info($wat=false)
- {
- /*
- | Als de gebruikers niet is ingelogd 'false' retourneren.
- */
- {
- return false;
- }
- /*
- | Anders even wat controles uitvoeren wat er moet gebeuren
- */
- else
- {
- /*
- | Alles van de gebruiker laten zien
- */
- if($wat === 'alles')
- {
- return self::$gebruikersinfo['info'];
- }
- /*
- | Een specefiek veld van de gebruiker laten zien
- */
- {
- return self::$gebruikersinfo['info'][$wat];
- }
- /*
- | Anders true retourneren (zie eerste if() lus van deze functie)
- */
- else
- {
- return true;
- }
- }
- }
- }
- /*
- | Meteen maar een nieuwe instantie van deze klasse maken en meteen de __constructor() functie laden
- | (in dit geval dus login(), de naam word door PHP bepaald aan de hand van de klasse naam)
- */
- $login = new login();
- /*
- | De benodigde database velden instellen
- | Elk veld dat je bij het registeren wilt hebben kan je hier toevoegen als nieuwe array waarde.
- | De syntax is: 'veldnaam:flag1|flag2'
- | Het veldnaam en de flags scheid je met dubbele punt. De flags scheid je van elkaar met een verticaal streepje.
- |
- | Flags:
- | verplicht = maak het veld verplicht
- | uniek = De ingevulde waarde voor dit veld mag maar een keer gebruikt worden. (handig voor gebruikersnamen)
- | min=3 = Minimaal in te vullen karakters is in dit geval 3.
- | max=10 = Maximaal in te vullen karakters is in dit geval 10.
- | ==wachtwoord2 = De ingevulde waarde van het huidge veld moet overeen komen met in dit geval de inhoud van het veld 'wachtwoord2'
- | email = Er wordt gecontrolleerd of de ingevulde waarde voldoet aan de eisen van een geldig e-mailadres.
- | md5 = Codeer de ingevulde waarde naar md5.
- */
- $login->database_velden = $database_velden;
- /*
- | En de init functie aanroepen
- */
- $login->init();
- ?>
9. Databasevelden
Dit inlogsysteem bied de mogelijkheid om vrij dynamisch database velden toe te voegen. Wil je bijvoorbeeld een veld erbij voor een e-mailadres, dan hoef je het veld alleen in de database te maken, en op te geven in de configuratie. In de configuratie kan je in de array het veld toevoegen en de benodige flags geven. Meer uitleg over de flags vind je in de config.
Als voorbeeld willen we een gebruikersnaam, wachtwoord en e-mailadres. Het wachtwoord gaan we coderen naar md5. Let op! Voor md5 moet je de optie in de configuratie ook op true zetten.
Plaats in de config de volgende code erbij (onder $database_velden = array()). Let wel op, er staan er al twee. Zorg dat je ze niet dubbel plaatst.
Het email veld wordt nu gecontrolleerd of het een geldig e-mailadres is, en of het veld is ingevuld. Het gebruikersnaamveld is verplicht, moet uniek zijn en heeft een minimum en maximum aantal karakters nodig. Hetzelfde geldt voor het wachtwoord veld, echter hebben we daar nog de optie md5 aan toegevoegd, en we willen dat het gelijk is aan het veld wachtwoord2.
Tot slot
Dit systeem is voor gevorden, omdat OOP mogelijk vrij lastig te begrijpen. Maar omdat het erg simpel in gebruik is, kunnen beginners het natuurlijk ook gebruiken.
Het maken van een wachtwoord vergeten functie is ook niet zo moeilijk, misschien dat ik die uitbreiding later maak.
Downloaden als: (zip)

