User authentication - Hashing¶
Inleiding¶
De titel van dit deel is User Authentication. Gelijk weer een omschrijving in het Engels... Vertaald naar normaal Nederlands levert dat het begrip gebruikersauthenticatie op. Hiermee wordt bedoeld dat voordat een gebruiker toegang wordt verleend op een aanvraag er een procedure wordt opgestart om te bepalen of het een rechtmatige aanvraag betreft.
Kortweg, het draait om het inloggen.
Tot nu toe heeft iedereen toegang tot elke pagina van de ontwikkelde webapplicaties. Vaak is het wenselijk de toegang te beperken tot alleen geregistreerde gebruikers. Het gaat in dit deel om de autorisatie en authenticatie van de gebruikers.
De onderwerpen die we gaan behandelen zijn:
- Password hashing
- De
Flask-Loginlibrary
Password hashing¶
Als een website gebruikersverificatie kent, zijn wachtwoorden en gebruikersnamen opgeslagen in een database. Om veiligheidsredenen zal nooit de letterlijke inhoud van het wachtwoord worden opgeslagen. Dat zou te gemakkelijk te achterhalen zijn voor hackers, en bovendien is het niet netjes wanneer een database-administrator gewoon beschikking zou hebben over wachtwoorden.
Een hashfunctie brengt hierbij uitkomst. Het is een algoritme dat een wachtwoord kan omtoveren naar een veilig alternatief. En met veilig wordt bedoeld dat een buitenstaander uit de hash niet kan achterhalen wat het originele wachtwoord is.
In de praktijk werkt dat als volgt: als een gebruiker een wachtwoord invoert, kan dit eenvoudig vergeleken worden met de opgeslagen hash. De hash is het enige wat opgeslagen wordt, en het is niet mogelijk (of in ieder geval erg moeilijk) om het wachtwoord te reconstrueren op basis van die hash.
Voor het werken met die hashes kan uit een tweetal beschikbare bibliotheken gekozen worden:
Beiden kunnen zeer goed gebruikt worden in een Flask-applicatie om te kunnen achterhalen of er een juist wachtwoord is ingevoerd. Van beide pakketten wordt een voorbeeld gegeven hoe het gebruikt kan worden.
Bcrypt en Werkzeug komen vaak mee als Flask geïnstalleerd wordt. Is dat niet het geval kunnen de pakketten op de bekende wijze opgehaald worden.
Bcrypt¶
Is Bcrypt aanwezig, is de eerste actie het importeren ervan. Daarna maken we een object aan van het type BCrypt() en gebruiken dat object om het wachtwoord te hashen:
In [1]: from flask_bcrypt import Bcrypt
In [2]: bcrypt = Bcrypt()
In [3]: hashed_pass = bcrypt.generate_password_hash('supergeheimwachtwoord')
Het wachtwoord wordt gehashed en bewaard in de variabele hashed_pass. Nadat het geprint is, is het echt niet meer te herleiden naar het origineel:
In [4]: print(hashed_pass)
b'$2b$12$rFOT5/VUiUpjODpcCn/0UONrhkQ2h224c7Srz3jk2qJOAUw2.xvyG'
Wordt het runnen herhaald, verschijnt er een andere hash.
Uiteraard nu weer een test naar de werking.
In [5]: bcrypt.check_password_hash(hashed_pass, 'verkeerdwachtwoord')
Out[5]: False
In [6]: bcrypt.check_password_hash(hashed_pass, 'supergeheimwachtwoord')
Out[6]: True
Werkzeug¶
Je kunt hetzelfde bereiken met Werkzeug, waarbij de syntax en de check zelfs nog iets simpeler is:
In [1]: from werkzeug.security import generate_password_hash,check_password_hash
In [2]: hashed_pass = generate_password_hash('supergeheimwachtwoord')
In [3]: print (hashed_pass)
pbkdf2:sha256:150000$hUiH149n$af71be7ff46588f9c5d93b4ec9f46ef1a64801d02434ee2057ca81b8bb2939cb
In [4]: check_password_hash(hashed_pass,'verkeerdwachtwoord')
Out[4]: False
In [5]: check_password_hash(hashed_pass,'supergeheimwachtwoord')
Out[5]: True
Het verschil tussen beiden is dat bij Werkzeug exact de juiste methoden binnengehaald worden en bij Bcrypt moet er soms een beetje over nagedacht worden. De keuze tussen deze pakketten is vrij arbitrair en ligt een beetje aan de voorkeuren van de ontwikkelaar.