Wachtwoorden: een hash in je server
De sha256 uit les 3 gaat nu je server in: /registreer bewaart
de hash, en /inloggen vergelijkt hash met hash.
Twee regels anders
Zet import hashlib bovenaan main.py. In /registreer wordt de regel
db[naam] = wachtwoord:
db[naam] = hashlib.sha256(wachtwoord.encode()).hexdigest()
In de database staat nu de hash. /inloggen moet daarom de hash van het
ingetypte wachtwoord vergelijken, met dezelfde berekening. De regel met de if
wordt:
if db.get(naam) == hashlib.sha256(wachtwoord.encode()).hexdigest():
Dat werkt omdat hetzelfde wachtwoord altijd dezelfde hash geeft.
Opnieuw registreren en inloggen
In gebruikers.db staan nog de wachtwoorden als gewone tekst. Gooi het bestand
weg en draai registreer.py en lees_database.py opnieuw. Maak daarna een
scriptje inloggen.py dat drie pogingen doet: Sara met haar wachtwoord, Sara
met een letter ernaast, en Bob, die geen account heeft:
import httpx
adres = "http://127.0.0.1:8000/inloggen"
pogingen = [("sara", "welkom123"), ("sara", "welkom124"), ("bob", "welkom123")]
for naam, wachtwoord in pogingen:
antwoord = httpx.post(adres, data={"naam": naam, "wachtwoord": wachtwoord})
print(f"{naam}, {wachtwoord}: {antwoord.json()['bericht']}")
Zo ziet je main.py er nu uit
import hashlib
from fastapi import FastAPI, Form, HTTPException
from sqlitedict import SqliteDict
app = FastAPI()
@app.post("/registreer")
async def registreer(naam: str = Form(...), wachtwoord: str = Form(...)):
with SqliteDict("gebruikers.db") as db:
if naam in db:
raise HTTPException(status_code=400, detail="Deze naam is al bezet")
db[naam] = hashlib.sha256(wachtwoord.encode()).hexdigest()
db.commit()
return {"bericht": f"Welkom, {naam}"}
@app.post("/inloggen")
async def inloggen(naam: str = Form(...), wachtwoord: str = Form(...)):
with SqliteDict("gebruikers.db") as db:
if db.get(naam) == hashlib.sha256(wachtwoord.encode()).hexdigest():
return {"bericht": "Ingelogd"}
return {"bericht": "Naam of wachtwoord klopt niet"}
Les 5 en 6 veranderen niets aan je server; in les 7 gaat /registreer weer om.
De wachtwoorden zijn niet meer te lezen. Maar kijk naar Sara en Noor: dezelfde code. Daar gaat les 5 over.
Er gaat iets mis
Sara kan niet inloggen
registreer.py geeft drie keer {'detail': 'Deze naam is al bezet'}, en
inloggen.py geeft ook bij Sara met welkom123
Naam of wachtwoord klopt niet.
Oorzaak: de oude gebruikers.db staat er nog. Daarin staat welkom123
als gewone tekst, en /inloggen vergelijkt dat met de hash van welkom123.
Die twee zijn nooit gelijk. Nieuwe accounts komen er niet bij, want de namen
bestaan al.
Oplossing: gooi gebruikers.db weg en draai registreer.py opnieuw.
lees_database.py laat daarna codes zien.
Opdrachten
Opdracht 1: Predict - Eén hoofdletter
Een vierde gebruiker, Tim, registreert met het wachtwoord Welkom123, met een
hoofdletter.
Vraag: lijkt de code bij Tim in de database op die van Sara? En zie je aan de database dat Tim en Sara bijna hetzelfde kozen?
Tip
Kijk naar de derde eigenschap in les 3.
Antwoord
Nee. Bij Tim staat
7bca025eff4fb877bea86faac56c909b65c97adfba23b7c1fb6b9772d34b420e, een heel
andere code dan de 2a5c5f26… van Sara. Eén letter anders is een compleet
andere hash, dus aan de database zie je niet dat hun wachtwoorden op elkaar
lijken.
Door naar les 5: zout.