Göm menyn

729G28 Webbprogrammering och databaser

Projekt del D


Innehåll

Del D

Syfte

I denna del ingår att ändra databasens schema mitt under utvecklingsarbetet samt att manipulera data i databasen via webben. Här ingår fundamentala säkerhetsaspekter av att använda relationsdatabaser för att hantera information i webbapplikationer.

Redovisning

Muntlig och skriftlig i samband med del C. Lämna också in en bild av det reviderade relationsschemat.

Förberedelser

Webb-labben bör vara avklarad innan denna del påbörjas.

Uppgifter

Man vill utöka systemet genom att tillåta vissa användare att lägga till nya spelare i databasen och sedan kunna ändra i dessa spelare. För att göra detta måste användaren skapa ett konto och kunna logga in med ett lösenord, och vi måste hålla rätt på om användaren är inloggad eller ej. Användaren identifieras med ett användarnamn, som måste vara unikt men en epostadress ska också finnas.
  1. Databasens schema behöver ändras för att kunna lagra registrerade användare (namn, epost och lösenord) och för spelare, vem som lagt in dem. Rita om relationsschemat och inför ändringarna i databasen. Notera när du väljer datatyp för lösenordet att funktionen bcrypt (se nedan) returnerar en lång sträng oavsett hur kort det okrypterade lösenordet är.
    Undersök vad som händer när du ändrar en befintlig tabell.
  2. Skapa två nya sidor, en för att logga in och en för att registrera en ny användare (eller en gemensam sida, om du vill), utgå gärna från signup.php. Se följande två uppgifter för hur det ska fungera.
  3. Börja med att utveckla sidan för att registrera ny användare (eller tänk ut hur det blir om du vill göra inloggning och ny användare på samma sida). För att skapa konto ska användaren mata in ett användarnamn, sin epostadress och ett lösenord. Alla dessa fält måste fyllas i (när användaren är ny).
    Användarnamnet måste vara unikt och får bara bestå av bokstäver och siffror.
    Epostadressen måste ha formen "tecken@tecken.domän".
    Lösenordet måste innehålla minst 8 tecken och ska sedan lagras så att det inte kan plockas ut ur databasen och avslöjas. Det görs genom att kryptera lösenordet innan det läggs in i databasen. Använd funktionen bcrypt för det.
    När allt är kontrollerat ska användaren läggas in i databasen. Tänk också på vad som lämpligen ska hända sedan.
  4. Gör sedan sidan för att logga in. Tänk på hur felmeddelanden ska formuleras. Tips: Använd phps SESSION för att hantera att användaren är inloggad. Länka till sidan för att skapa ny användare, om du gjort en separat sida för det.
  5. Lägg in en länk till inloggnings-sidan från home.php, som visas ifall användaren inte redan är inloggad. Om användaren redan är inloggad, visa användarnamnet. Om du vill, lägg till möjligheten att logga ut för att kunna kontrollera att allt fungerar som det ska.
  6. Skapa en sida för att mata in en ny spelare (utgå från addplayer.php om du vill). Det ska gå att mata in följande data: Spelarens namn (obligatorisk), vikt, längd, födelsedatum och en beskrivande text. Vilket lag spelaren kommer att läggas till i ska synas. På denna sidan ska lämpliga typer för inmatningsformat användas (Tips: HTML-taggen Input) som matchar de olika formaten på inmatningsdata och kontroller av indata ska göras så att inget farligt kan hända (se nedan). Notera att användaren inte ska ge spelaren ett ID, det ska skapas så att det inte krockar med något befintligt. Kom också ihåg att lagra användaren som lade in spelaren. Gör så att om man är inloggad visas länken till denna sida på team.php.
  7. Ändra sidan där information om spelare visas (eller gör en ny sida om du vill) så att, om användaren är inloggad som den användare som lagt in spelaren, så kan man uppdatera information om spelaren. Även hör ska indata kontrolleras att det är rätt typ och inte skadligt, men här är inget krav på att något måste matas in. Tänk på att om användaren inte matar in något i ett fält ska det fältet behålla sitt ursprungliga värde i databasen, inte tömmas. Tips: Ett sätt att hantera detta är att lägga in ett startvärde i textfält då textfältet skapas.
  8. De nya sidorna ska ha brödsmulor som följer samma logik som för del C.
  9. Användaren ska få ett meddelande om framgång eller misslyckande vid all inmatning till databasen. Vid misslyckande ska ett informativt felmeddelande visas. Tänk på att vid all nätverksuppkoppling kan man tappa kontakten med databasen.
  10. Skydd för SQL-Injections ska implementeras varje gång ett kommando till databasen innehåller data från klientsidan (se nedan för tips).
  11. Skydd för XSS ska implementeras för alla inmatningsfält som senare visas för användare, så att de skyddas mot skadlig Javascript/HTMLkod (se nedan för tips).
  12. HTML-koden ska validera i w3's validator på denna sida (enklast genom att be webbläsaren visa källkoden, klipp ut och klistra in i validatorn). .
  13. Eventuell ny CSS-kod ska validera i denna validator.

Tips till uppgifterna i Del D

  • Om du tycker att även de gamla spelarna borde ha en skapare kan du, när du ändrar i databasen, lägga in en användare för dem, t.ex. "Admin". Den kan sedan sättas som default-värde när du skapar den nya kolumnen i spelar-tabellen.
  • Se till att hantera situationen då en användare försöker registrera sig med en redan existerande epostadress (eller namn) och när användare försöker logga in med en epostadress som inte finns, eller fel lösenord. Tänk på vilka felmeddelanden som ges, så att de inte avslöjar onödigt mycket (t.ex vid fel lösen bör man inte avslöja att användarnamnet finns).
  • Tänk på vad som ska hända när man skapat en ny användare. Ska man då tas till inloggningssidan och logga in, eller är man redan inloggad? Det kan uppfattas som jobbigt att behöva logga in efter att ha skapat ett konto - man gör det ju för att logga in. Men det finns faktiskt en poäng med att tvinga användaren att logga in efter att ha skapat ett konto: att upprepa lösenordet en gång till gör att man minns det bättre.
  • XSS: Notera att för kursens syften räcker funktionen htmlspecialchars, men det är inte en komplett, allmängiltig lösning. En mer fördjupad diskussion finns i den här artikeln.
    Testa om din applikation är sårbar genom att mata in detta i ett textfält, t.ex. spelarnamn eller info, när du lägger till ny spelare: <script>alert("HACKED")</script> och spara spelaren till databasen. Gå sedan in på den nya spelarens sida.
  • SQL injection: Din applikation låter användare fritt ladda upp data till din databas. I dessa fall så måste man sanera indata så att försök att manipulera själva databasen förhindras. I PHP uppnås detta enklast genom att använda sig av "förberedda", prepared SQL statements. Exempel på hur det kan hanteras:
    $fornamn = "Kalle";
    
    $query = "SELECT efternamn, favoritfarg FROM personer WHERE fornamn = ?";
    $statement = $conn->prepare($query);
    $statement->bind_param('s', $fornamn);
    $statement->execute();
    $statement->bind_result($efternamn, $favoritfarg);
    
    while ($statement->fetch()) {
        echo "<p>Kalle " . $efternamn . " gillar " . $favoritfarg . "</p>";
    }
    Läs på om de olika php-funktionerna som används ovan, t.ex. i php-manualen. Ett alternativ till bind_result är get_result och ett alternativ till fetch är då fetch-assoc. När man inte behöver skydda sig mot injections (för att ingen användardata används i frågan) är query ett alternativ till execute. Man kan använda liknande kod för en INSERT query (då behöver man dock inte hämta några resultatrader). För den intresserade finns fördjupningsmaterial om SQL Injection (PHP.net).