Index

Beveiliging

Het IP adres van de bezoeker
Als een bezoeker je pagina opvraagt, dan bekom je zijn IP adres. Je kan daarmee een bezoeker tracken over je site (welke pagina's hij bezocht heeft, hoe lang hij gebleven is, ...) maar je kan deze informatie niet gebuiken om de bezoeker met zekerheid te identificeren. De meeste gebruikers hebben geen vast IP, dus het adres dat ze toegewezen krijgen veranderd iedere keer dat ze online gaan. Vaak wordt er ook gewerkt met een proxy; dat is een server dat als tussenstation fungeert voor alle aanvragen. Vroeger had een proxy meer nut (toen het internet trager was) omdat de proxy ook als cache fungeerde. Nu heeft een proxy totaal geen nut meer, maar bij de meeste gebruikers staat de configuratie nog altijd ingesteld op "gebruik een proxy". Gezien vanaf de webserver hebben alle gebruikers die via proxy werken allemaal dezelfde IP: dat van de proxy.


Authentification
Bij authentificatie moet een gebruiker zich aanmelden door middel van een login en paswoord. Dit is een ideale methode om bepaalde delen van een website af te schermen (bijvoorbeeld enkel voor betalende gebruikers). Het grote voordeel is dat de webserver de volledige procedure op zich neemt, je hoeft geen extra stappen te ondernemen. Je moet enkel aangeven welke directories door een login en paswoord beschermd moeten worden.
De pagina's die opgevraagd worden worden ongecodeerd doorgestuurd, dus deze methode is bijvoorbeeld niet aangewezen voor het opvragen van bijvoorbeeld rekeninguitreksels (daarvoor moet je het https-protocol gebruiken).


Gebruiker volgen
HTTP is per definitie een stateless protocol: iedere keer dat een bezoeker een pagina aanvraagt wordt er een nieuwe verbinding opgezet. De server weet niet hoe de bezoeker op die pagina is terechtgekomen, en dat kan voor problemen zorgen als er bijvoorbeeld een online winkel opgezet wordt.

Veronderstellen we dat een bezoeker

  • moet inloggen
  • artikels bestellen
  • en bevestigen
    Bij iedere stap wordt er een programma gestart: login.exe, order.exe, confirm.exe.

    In login.exe (de enige geldige entry point), maken we een record aan voor de klant aan de hand van zijn login en de huidige tijd. Onze klant wordt aldus intern geïdentificeerd door volgende sleutel: Ew3Zq0ea (sessie identificatie). We moeten ervoor zorgen dat de sleutel uniek is (als de klant-login uniek is is dit geen probleem). We slaan de naam lokaal op als een bestand Ew3Zq0ea.1 en sturen de sessie-identificatie door als een hidden field.

    In order.exe controleren we of er een bestand bestaat voor onze klant: we vergelijken de sessie-identifikatie van de klant met onze interne lijst:

  • bestaat de identifikatie? (als Ew3Zq0ea.1 of Ew3Zq0ea.3)
  • klopt de tijd? (we geven de gebruiker een paar minuten respijt voor het invullen van het formulier)
  • is de klantennaam geldig? (als we de klantennaam versleutelen, bekomen we de sessie id.?)
    Indien ja, kunnen we de aanvraag afhandelen. We wissen de oude identifikatie en sturen we de gebruiker een nieuwe identificatie als hidden field en slaan de identifikatie eveneens lokaal op als 7GHioNpQ.2

    In confirm.exe, volgen we dezelfde procedure. Als de sessie identifikatie overeenkomt voeren we de transaktie uit. Weer een tevreden klant!

    order.exe kan bereikt worden via zowel login.exe (de normale manier), maar ook via confirm.exe (als de gebruiker op zijn stappen terugkeert). In dit geval moeten we de order.exe-formulier opnieuw aan de klant aanbieden, maar nu met de reeds ingevulde velden, zodat de klant de gegevens enkel moet wijzigen indien nodig.

    Wat zetten we in de identifikatiebestand? Eigenlijk moet daar niets ingevuld worden: de meeste informatie zit reeds in de naam zelf: klantenlogin, referer-pagina (1, 2 of 3) en time stamp. Het bestand kan bijvoorbeeld gebruikt worden om de bestelde artikels in op te slaan, totdat de bestelling volledig verwerkt is. Dit bestand zit veilig op de server, het kan dus gebruikt worden om gegevens op te slaan die niet zichtbaar mogen zijn voor de klant (winstmarge,...)


    Semaphores
    De sessie identifikatie is eigenlijk een soort semaphore-bestand dat ervoor moet zorgen dat als de klant meerdere keren op de SUBMIT-knop drukt, de handeling slechts éénmaal uitgevoerd wordt (anders wordt de bestelling bijvoorbeeld driemaal uitgevoerd).

    Bij het begin van de verwerking openen we de sessie identifikatiebestand als LOCK READ WRITE (dit is trouwens de default-waarde). Indien het bestand niet exclusief geopend kan worden is dit een teken dat het bestand reeds in gebruik is door eenzelfde klant dat meermalen op de SUBMIT-knop gedrukt heeft. De eerste uitvoering kan het bestand openen (en locken), de andere uitvoeringen mogen gerust afgebroken worden.
    Als het bestand niet bestaat is het een teken van het volgende:

  • de verwerking is reeds gebeurd (maar de klant drukte nog een keer op SUBMIT juist voordat het antwoord verstuurd werd)
  • de sessie identifikatie bestaat niet (een hacker die probeert in het systeem te dringen)
  • de sessie identifikatie klopt niet (de klant gebruikt een link uit zijn history of volgt niet de juiste stappen om te bestellen)

    In onze verwerking moeten we ervoor zorgen dat de sessie identifikatiebestand (semaphore) bestaat op het ogenblik dat de verwerking gestart wordt; dat de semaphore gelockt kan worden. Indien aan deze voorwaarden voldaan kan worden, mag de verwerking plaatsvinden. Op het einde wissen we de semaphore en maken we indien nodig een volgende semaphore aan voor de volgende stap in de bestelling.


    Optimistic concurrency

    Wie nog in het DOS-tijdperk geprogrammeerd heeft, kent waarschijnlijk het LOCK-statement, waarbij men bestanden of records kon blokkeren, zodat een andere applikatie de gegevens niet kan wijzigen. Bij netwerk-toepassingen kunnen verschillende gebruikers dezelfde gegevens proberen te veranderen. Bij moderne databases wordt er niet meer gewerkt met lock-toestanden, maar gebruikt men een algoritme dat optimistic concurrency heet. Optimistic concurrency is ideaal voor web-toepassingen, maar gewone databases (SQL) gebruiken vaker het multiversion concurrency control.

    Veronderstel dat een record uit de database moet gewijzigd worden. Daarvoor zijn er twee programma's: get_record dat de huidige gegevens van de database opvraagt en ze aan de gebruiker toont in de vorm van een formulier dat gewijzigd kan worden en put_record dat het gewijzigd formulier terug in de database schrijft.

    Veronderstel dat twee gebruikers eenzelfde record willen wijzigen:

  • 1 Gebruiker_A vraagt record_1 aan.
    We blokkeren record_1 niet; bij webtoepassingen is het gebruik van een LOCK niet te doen: een gebruiker kan gewoon zijn werkpost verlaten of het programma afsluiten zonder de LOCK op te heffen.
  • 2 Gebruiker_B kan het record ook lezen.
  • 3 Gebruiker_A heeft het record gewijzigd
    Met put_record worden de gewijzigde gegevens opnieuw in de database geschreven.
  • 4 Wanneer Gebruiker_B zijn gegevens in de database terugplaatst zijn de wijzigingen die door Gebruiker_A aangebracht zijn verloren.
    Met onze stateless systeem is het niet mogelijk te weten dat de gegevens ondertussen gewijzigd zijn geweest door een andere gebruiker.
  • Records bestaan uit gebruiker-data (artikelnummer, naam, beschrijving, prijs) en systeem data (bijvoorbeeld pointers naar andere records in dezelfde database (vervangend artikel) of een andere database (leverancier)). Meestal is het niet al te erg als er user data gewijzigd wordt, maar als systeemdata verkeerd gewijzigd wordt kan dit catastrofale gevolgen hebben voor de integriteit van de database.

    Hoe kunnen we weten of een record gewijzigd wordt door twee gebruikers?
    Dit kan heel eenvoudig door een version-control veld bij te voegen bij iedere record: artikel.writecount (writecount kan een gewone integer zijn). iedere keer dat een record gelezen wordt, wordt de version-control veld mee gelezen en in de semaphore van de betreffende user geschreven.
    Bij het schrijven wordt de version-control met één verhoogd.
    Als Gebruiker_B op zijn beurt de gewijzigde gegevens wilt terugschrijven, dan zal het programma merken dat de version control van het record niet meer overeenkomt met de version control zoals in de semaphore opgetekend werd (de originele waarde). Het terugschrijven van de gegevens kan niet doorgaan. We bieden Gebruiker_B het record opnieuw aan, maar gebruiken nu de versie zoals door Gebruiker_A weggeschreven werd.

    De database en het onderliggend operating system moeten atomic write ondersteunen om optimistic concurrency mogelijk te maken. Een atomic write is een reeks handelingen die bij elkaar horen en die niet halverwege onderbroken mogen worden. Bij een multi-tasking systeem loop je altijd het gevaar dat je programma op een bepaalde plaats (en tijd) onderbroken wordt, met alle nare gevolgen vandien voor de database integriteit.

    De benaming optimistic concurrency werd gekozen omdat we ervan uitgaan dat de gegevens vaker gelezen zullen worden en slechts in uitzonderlijke gevallen veranderd worden. Als ze veranderd worden, is het uitzonderlijk dat twee gebruikers dezelfde records proberen te wijzigen. Deze veronderstelling klopt bij web-transacties. De benaming "mid-air collision" wordt gebruikt als de noodprocedure in gang moet gezet worden (gegevens simultaan door twee gebruikers gewijzigd).

    Index

    Individuele landingspage bezoekers: