HTML van een bezoeker: in je eigen project
Je weet nu waar tekst van een bezoeker HTML kan worden: in een f-string in een
HTMLResponse, ook als de tekst uit de URL komt, in een template met |safe of
met een andere extensie dan .html, en in JavaScript met innerHTML. Loop je
gastenboek, of een eigen project dat je bouwde, langs op die plekken.
Werk in je eigen project, niet in de map veiligheid-xss. Test daarna met je
eigen server op 127.0.0.1.
Zoeken en testen
Zoek in je main.py naar HTMLResponse(f, in je templates naar |safe, en in
je JavaScript naar innerHTML. Een {{ }} in een .html-template is al
veilig. Wat je vindt, maak je veilig zoals in de lessen hiervoor: escape() in
een f-string, |safe weg, en textContent in plaats van innerHTML.
Start daarna je eigen server, en schrijf in je eigen gastenboek een bericht
<b>vet</b>.
Er gaat iets mis
NameError: name 'escape' is not defined
Na het versturen verschijnt er niets onder het formulier, maar je bericht staat
wel in de lijst. In het tabblad Netwerk heeft POST /gastenboek een 500,
en in de terminal van je server eindigt de foutmelding met:
NameError: name 'escape' is not defined
Oorzaak: je zette escape(…) in de return, maar from html import escape
staat niet bovenaan main.py. Het bericht is dan al opgeslagen; pas de return
gaat mis. htmx zet een 500 niet in de pagina.
Oplossing: zet from html import escape bij je andere imports.
<b> op je pagina
In je lijst staat letterlijk <b>vet</b>, met de codes in plaats
van de haakjes.
Oorzaak: je zette escape() om een waarde die je aan een template geeft.
Jinja escapet die dan nog een keer, en van de & in < maakt hij &.
Oplossing: geef het template de tekst zoals hij is; het template escapet
zelf. escape() hoort alleen in een f-string.
Meer uitleg: Templates escapen vanzelf
Opdrachten
Opdracht 1: Make - In je eigen project
Zoek in je eigen project elke plek waar tekst van een bezoeker in HTML komt, en zorg dat die overal tekst blijft.
Tip
Na de basis en de uitbreidingen staat er meestal maar één f-string met HTML in
je main.py: de return van je POST /gastenboek als je het htmx-formulier
gebruikt. Begin daar.
Antwoord
Loop deze lijst af:
- Een template dat op
.htmleindigt, escapet alles tussen{{ }}. Daar hoef je niets te doen. - Staat er
|safeachter tekst van een bezoeker, haal het weg. - Staat er een parameter van je endpoint in een
HTMLResponse(f"…"), zet erescape()omheen, of gebruik een template. Dat geldt ook voor een query-parameter zoals?term=, die niets opslaat. - Zet je JavaScript tekst uit een veld of uit de URL in de pagina, gebruik dan
textContenten nietinnerHTML. De tekenteller uit JavaScript erbij doet dat al goed. - Heb je het recept Een formulier versturen uit het
htmx-overzicht overgenomen, kijk dan of daar
escape(naam)staat; dat is later aan het recept toegevoegd. Na Sessies komt de naam uit de sessie: dan is hetescape(mijn["naam"]). - Ook een naam bij
/registreerkomt van een bezoeker. Wie zich registreert als<b>Sara</b>, staat zo in je lijst en op je detailpagina; in een.html-template blijft dat tekst.
Gebruik je in je gastenboek het htmx-formulier, dan is dat de return van je
POST /gastenboek. Zet from html import escape bij je imports, en laat de
return zo eindigen:
return HTMLResponse(f"Bedankt, {escape(mijn['naam'])}. Je bericht staat in het gastenboek.")
Heb je de sessies niet gebouwd, dan staat er escape(naam).
Stuurt je POST /gastenboek nog door met een RedirectResponse, dan zet hij
geen tekst in HTML, en hoeft er niets bij. Je lijst, je detailpagina en
berichten.html zijn templates op .html; ook daar komt niets bij.
Test het door in je eigen formulier <b>vet</b> in te vullen: je moet de
haakjes zien, en niets vetgedrukt.
Door naar les 10: in de praktijk.