Inloggning med ett konto

I denna guiden får du lära dig hur man kan skapa en lösenordsskyddad hemsida med inloggning (för ett konto).

Den här guiden förutsätter att du har läst de fem första lektionerna i vår PHP-skola (första lektionen till och med lektionen om villkorssatser). Om du inte har det finns det troligtvis kod nedan du inte förstår och som inte förklaras här. Fortsätt läs på egen risk om du har skolkat!

Du kan redan nu tjuvkika på vad vi kommer åstadkomma genom att gå till [FILEN]. Där kan du komma till den lösenordsskyddade sidan genom att logga in med användarnamnet "Demo" och lösenordet "1234" (testa gärna att skriva in fel inloggningsuppgifter först).

Att åstadkomma detta är faktiskt inte så svårt. Vi behöver en sida med inloggningsformuläret, och på samma sida sköter vi även själva inloggningen. Formuläret kommer alltså skickas till samma sida som formuläret är på. Med hjälp av funktionen isset kan vi avgöra om formuläret skickats eller om man besöker sidan för första gången.

<?php if(isset($_POST['namn'])){ /* Om formuläret har skickats kommer koden i denna villkorssatsen att köras. */ // Skriv ut något (enbart för utvecklingssyfte) echo 'Formuläret postades!'; } ?> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>Logga in</title> <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> </head> <body> <h1>Logga in</h1> <p>Logga in med formuläret nedan för att nå de lösenordsskyddade sidorna.</p> <form action="loggaIn1.php" method="post"> <input type="text" name="namn"><br> <input type="text" name="kod"><br> <input type="submit" value="Logga in"> </form> </body> </html>

På rad 9 ovan skickar vi output till webbläsaren innan själva HTML-koden skickas (om man skickat formuläret). Detta är egentligen fel (det första som ska finnas i en HTML-fil är ju <!doctype>), men det är enbart för utvecklingssyfte för att se att formuläret fungerar som det ska (testa att skicka det själv). I den färdiga versionen kommer det inte att vara så.

Men hur kan man avgöra om besökaren angett rätt inloggningsuppgifter? Jo, det kan man enkelt avgöra med en villkorssats. Vi behöver dock först avgöra vad som ska vara rätt inloggningsuppgifter. I vårt fall låter vi "Demo" vara rätt namn och "1234" vara rätt lösenord.

<?php if(isset($_POST['namn'])){ if($_POST['namn'] == 'Demo' && $_POST['kod'] == '1234'){ /* Har man angett rätt inloggningsuppgifter körs koden i denna villkorssatsen */ // Skriv ut något (enbart för utvecklingssyfte) echo 'Du har angett rätt inloggningsuppgifter'; }else{ /* Koden inom dessa måsvingar körs om man angett fel inloggningsuppgifter */ // Skriv ut något (enbart för utvecklingssyfte) echo 'Du har angett fel inloggningsuppgifter'; } } ?> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>Logga in</title> <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> </head> <body> <h1>Logga in</h1> <p>Logga in med formuläret nedan för att nå de lösenordsskyddade sidorna.</p> <form action="loggaIn2.php" method="post"> <input type="text" name="namn"><br> <input type="text" name="kod"><br> <input type="submit" value="Logga in"> </form> </body> </html>

Om man angett rätt inloggningssidor kan man slussa iväg besökaren till en av de skyddade inloggningssidorna med hjälp av funktionen header. Eftersom besökaren inte ska se något mer av sidan med formuläret på så anropar vi även direkt efteråt funktionen exit, som ser till att ingen mer kod nedanför exekveras. Vi låter den lösenordsskyddade sidan heta hemligSida3A.php.

<?php if(isset($_POST['namn'])){ if($_POST['namn'] == 'Demo' && $_POST['kod'] == '1234'){ /* Besökaren har angett korrekt inloggningsuppgifter, skicka iväg den till en lösenordsskyddad sida. */ header("Location: hemligSida3A.php"); exit(); }else{ // Skriv ut något (enbart för utvecklingssyfte) echo 'Du har angett fel inloggningsuppgifter'; } } ?> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>Logga in</title> <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> </head> <body> <h1>Logga in</h1> <p>Logga in med formuläret nedan för att nå de lösenordsskyddade sidorna.</p> <form action="loggaIn3.php" method="post"> <input type="text" name="namn"><br> <input type="text" name="kod"><br> <input type="submit" value="Logga in"> </form> </body> </html>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>Lösenordsskyddad Sida A</title> <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> </head> <body> <h1>Lösenordsskyddad sida A</h1> <p>Vill du även besöka lösenordsskyddad <a href="hemligSida3B.php">sida B</a>?</p> </body> </html>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>Lösenordsskyddad Sida B</title> <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> </head> <body> <h1>Lösenordsskyddad sida B</h1> <p>Gå tillbaka till lösenordsskyddad <a href="hemligSida3A.php">sida A</a>.</p> </body> </html>

Det fungerar! Nu ska vi bara fixa till så ett felmeddelande visas om besökaren anger felaktiga inloggningsuppgifter, men hur kan man göra det på ett bra sätt? Det kan ju inte skrivas ut där det står nu, för då kommer det innan själva HTML-koden, vilket det inte får, utan vi vill skriva ut det precis nedanför rubriken "Logga in" på rad 29. Man kan tro att det bara är att flytta all PHP kod, men det kommer inte fungera (testa själv med koden nedan att logga in med rätt inloggningsuppgifter).

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>Logga in</title> <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> </head> <body> <h1>Logga in</h1> <?php if(isset($_POST['namn'])){ if($_POST['namn'] == 'Demo' && $_POST['kod'] == '1234'){ header("Location: hemligSida4A.php"); exit(); }else{ // Skriv ut att fel inloggningsuppgifter angetts echo '<p>Du har angett fel inloggningsuppgifter.</p>'; } } ?> <p>Logga in med formuläret nedan för att nå de lösenordsskyddade sidorna.</p> <form action="loggaIn4.php" method="post"> <input type="text" name="namn"><br> <input type="text" name="kod"><br> <input type="submit" value="Logga in"> </form> </body> </html>

Varför fungerar inte detta då? Jo, problemet är att vi på rad 15 skickar en header, och dessa måste skickas innan någon output skickas till webbläsaren. På raderna 1-9 skickar vi massor av output, vilket förstör det hela. Man kan tycka att det är dumt att det fungerar så här, men om man tänker efter är det logiskt. Just nu börjar vi skicka output till webbläsaren, och sedan skickar vi en header som talar om att besökaren istället ska gå till en annan sida. All output vi skickat har alltså varit helt i onödan! Därför ska headers alltid skickas först, innan någon output skickas.

Denna lösningen fungerar alltså inte. Den bästa lösningen vi kan få är nog att ha en variabel som håller koll på om det är en misslyckad inloggning eller ej.

<?php // En variabel som håller koll på om det är en misslyckad inloggning $misslyckadInloggning = false; if(isset($_POST['namn'])){ if($_POST['namn'] == 'Demo' && $_POST['kod'] == '1234'){ header("Location: hemligSida5A.php"); exit(); }else{ // Misslyckad inloggning! Ändra variabeln som håller koll på det $misslyckadInloggning = true; } } ?> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>Logga in</title> <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> </head> <body> <h1>Logga in</h1> <?php // Om det är en misslyckad inloggning, skriv ut ett felmeddelande if($misslyckadInloggning){ echo '<p>Du har angett fel inloggningsuppgifter.</p>'; } ?> <p>Logga in med formuläret nedan för att nå de lösenordsskyddade sidorna.</p> <form action="loggaIn5.php" method="post"> <input type="text" name="namn"><br> <input type="text" name="kod"><br> <input type="submit" value="Logga in"> </form> </body> </html>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>Lösenordsskyddad Sida A</title> <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> </head> <body> <h1>Lösenordsskyddad sida A</h1> <p>Vill du även besöka lösenordsskyddad <a href="hemligSida5B.php">sida B</a>?</p> </body> </html>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>Lösenordsskyddad Sida B</title> <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> </head> <body> <h1>Lösenordsskyddad sida B</h1> <p>Gå tillbaka till lösenordsskyddad <a href="hemligSida5A.php">sida A</a>.</p> </body> </html>

Nu fungerar det galant, men egentligen är inte sidorna lösenordsskyddade. Visst, om man loggar in med rätt uppgifter kommer man till de skyddade sidorna, men det finns inget som hindrar en besökare från att direkt gå till dessa sidor med sin webbläsare utan att logga in först. Till exempel kan du gå till hemligSidaB.php genom att trycka på länken överst i kodrutan ovan, så sidorna är inte lösenordsskyddade på riktigt.

För att få de lösenordsskyddade sidorna lösenordsskyddade på riktigt måste vi först på dessa sidor kontrollera att besökaren faktiskt har loggat in med hjälp av formuläret. Det låter som att lösningen kommer bli väldigt komplex, men med funktionen session_start och variabeln $_SESSION kan man lösa det ganska enkelt. När man framgångsrikt loggat in lägger vi till ett värde i $_SESSION (som enbart går att få på detta sättet), och på de lösenordsskyddade sidorna kollar vi bara besökaren har fått detta värde.

<?php // Anropa sessions_start, så vi har tillgång till $_SESSION session_start(); $misslyckadInloggning = false; if(isset($_POST['namn'])){ if($_POST['namn'] == 'Demo' && $_POST['kod'] == '1234'){ // Spara ett värde i $_SESSION, som visar att man loggat in via formuläret $_SESSION['inloggad'] = true; header("Location: hemligSida6A.php"); exit(); }else{ $misslyckadInloggning = true; } } ?> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>Logga in</title> <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> </head> <body> <h1>Logga in</h1> <?php if($misslyckadInloggning){ echo '<p>Du har angett fel inloggningsuppgifter.</p>'; } ?> <p>Logga in med formuläret nedan för att nå de lösenordsskyddade sidorna.</p> <form action="loggaIn6.php" method="post"> <input type="text" name="namn"><br> <input type="text" name="kod"><br> <input type="submit" value="Logga in"> </form> </body> </html>
<?php // Anropa sessions_start, så vi har tillgång till $_SESSION session_start(); // Om man inte loggat in via inloggningsformuläret... if(!isset($_SESSION['inloggad'])){ // ...skicka besökaren till sidan med inloggningsformuläret header("Location: loggaIn6.php"); exit(); } ?> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>Lösenordsskyddad Sida A</title> <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> </head> <body> <h1>Lösenordsskyddad sida A</h1> <p>Vill du även besöka lösenordsskyddad <a href="hemligSida6B.php">sida B</a>?</p> </body> </html>
<?php // Anropa sessions_start, så vi har tillgång till $_SESSION session_start(); // Om man inte loggat in via inloggningsformuläret... if(!isset($_SESSION['inloggad'])){ // ...skicka besökaren till sidan med inloggningsformuläret header("Location: loggaIn6.php"); exit(); } ?> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>Lösenordsskyddad Sida B</title> <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> </head> <body> <h1>Lösenordsskyddad sida B</h1> <p>Gå tillbaka till lösenordsskyddad <a href="hemligSida6A.php">sida A</a>.</p> </body> </html>

Notera att värdet $_SESSION['inloggad'] tilldelas på rad 13 i filen loggaIn6.php aldrig används, och kan vara vad som helst. I de lösenordsskyddade filerna kollar vi enbart om $_SESSION['inloggad'] har fått något värde, aldrig vad värdet är. Det verkar dock logiskt att tilldela det värdet true.

De här sidorna är verkligen lösenordsskyddade, för man måste logga in via formuläret för att kunna se dem. Mycket mer behövs faktiskt inte göras, dock ska vi göra det möjligt att logga ut. Det kan man åstadkomma genom att helt enkelt ta bort $_SESSION['inloggad'], vilket kan göras med funktionen unset. Sedan kan man tycka att det rätta användarnamnet och lösenordet nu är hårdkodat i filen, vilket är dåligt. Att det är hårdkodat betyder att det står inne i koden (oftast på flera ställen, men så är det ju inte i detta fallet), men genom att låta dessa värden ligga i ett par variabler i början av filen blir vi av med det. Då blir det enkelt att byta användarnamn och lösenord i framtiden, då man inte behöver gå in i koden och krångla, utan enbart ändra värden på ett par variabler.

<?php session_start(); // Lägg rätt användarnamn och lösenord i variabler $rättNamn = 'Demo'; $rättKod = '1234'; $misslyckadInloggning = false; if(isset($_POST['namn'])){ // Jämför med variabler istället för hårdkodade strängar if($_POST['namn'] == $rättNamn && $_POST['kod'] == $rättKod){ $_SESSION['inloggad'] = true; header("Location: hemligSida7A.php"); exit(); }else{ $misslyckadInloggning = true; } } ?> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>Logga in</title> <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> </head> <body> <h1>Logga in</h1> <?php if($misslyckadInloggning){ echo '<p>Du har angett fel inloggningsuppgifter.</p>'; } ?> <p>Logga in med formuläret nedan för att nå de lösenordsskyddade sidorna.</p> <form action="loggaIn7.php" method="post"> <input type="text" name="namn"><br> <input type="text" name="kod"><br> <input type="submit" value="Logga in"> </form> </body> </html>
<?php session_start(); if(!isset($_SESSION['inloggad'])){ header("Location: loggaIn7.php"); exit(); } ?> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>Lösenordsskyddad Sida A</title> <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> </head> <body> <h1>Lösenordsskyddad sida A</h1> <p>Vill du även besöka lösenordsskyddad <a href="hemligSida7B.php">sida B</a>?</p> <!-- Länk som loggar ut besökaren --> <p>Du kan även <a href="loggaUt7.php">logga ut</a>.</p> </body> </html>
<?php session_start(); if(!isset($_SESSION['inloggad'])){ header("Location: loggaIn7.php"); exit(); } ?> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>Lösenordsskyddad Sida B</title> <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> </head> <body> <h1>Lösenordsskyddad sida B</h1> <p>Gå tillbaka till lösenordsskyddad <a href="hemligSida7A.php">sida A</a>.</p> <!-- Länk som loggar ut besökaren --> <p>Du kan även <a href="loggaUt7.php">logga ut</a>.</p> </body> </html>
<?php // Anropa sessions_start, så vi har tillgång till $_SESSION session_start(); // Om man är inloggad, logga ut if(isset($_SESSION['inloggad'])){ unset($_SESSION['inloggad']); } // Skicka iväg besökaren till inloggningssidan header("Location: loggaIn7.php"); exit(); ?>