Hoofdstuk 9
CORS
Toestemming om te lezen
Hoofdstuk 8 ging over een verzoek dat een andere pagina niet zou moeten kunnen doen. Dit hoofdstuk begint bij de omgekeerde wens.
De leeslijst krijgt een tweede frontend, op https://app.reading.example. Dat is een van de vier namen uit hoofdstuk 8, en hij is van jou. Een script op de pagina’s daarvan wil GET https://reading.example/about sturen en het antwoord tonen.
De twee hosts zijn één site en twee
De server mag ja zeggen
De same-origin policy heeft één
access-control-allow-origin: https://app.reading.example
Met die header zegt de server: een pagina op deze origin mag dit antwoord lezen. Die afspraak heet
the page on the browser the server at
app.reading.example reading.example
1. asks for GET /about
----------------->
2. sends the request, and adds
origin: https://app.reading.example
--------------->
3. answers as always,
and may add
access-control-allow-origin
<---------------
4. looks at that header, and hands
<--------------- the response over, or keeps it
Het script van de pagina vraagt zijn browser om het verzoek.
De browser verstuurt het. Omdat het verzoek naar een andere origin gaat, voegt de browser een header
Origintoe met de origin van de pagina. De pagina kan die header niet veranderen.De server antwoordt zoals altijd. Als hij wil, voegt hij
Access-Control-Allow-Origintoe.De browser kijkt naar die ene header. Hij geeft het antwoord alleen aan het script als de header de origin van de pagina noemt, of als hij
*is, wat voor elke origin staat. In alle andere gevallen krijgt het script niets.
Kijk wie er in elke stap handelt. De server geeft de toestemming in de derde stap. De browser dwingt hem af in de vierde. De pagina heeft helemaal niets te zeggen.
De header Origin uit de tweede stap is dezelfde die je server al leest. In hoofdstuk 8 gebruikte hij die header om een vervalste POST te weigeren. Nu vertelt dezelfde header de server welke pagina het vraagt, zodat hij die pagina bij naam kan antwoorden.
Volg het
Het volgende blok is de vierde stap: een antwoord-"*", of verander PAGE in "https://notes.reading.example", en voer het elke keer opnieuw uit.
Dit blok is een schets van de regel, en het verstuurt niets. In les 2 schrijf je de echte controle in mini_browser.py.
Wie beslist er bij elk verzoek of een pagina een antwoord van een andere origin mag lezen?
Wat de server deed voordat de browser besliste
Bij de vierde stap is de server klaar. Hij ontving het verzoek, voerde handle() uit en stuurde het hele antwoord. Als de browser het lezen weigert, wordt er niets teruggedraaid. Het antwoord kwam aan, en het werd voor een script achtergehouden.
Een ontbrekende header maakt dus nooit iets ongedaan. Als het verzoek iets op de server veranderde, is die verandering gedaan. Dat is nog eens de les van hoofdstuk 8: lezen is wat de browser bewaakt, en een verzoek dat iets verandert, heeft dat al gedaan voordat er naar een header wordt gekeken.
Een pagina op een andere origin post een formulier, en de server voert het uit. Het antwoord heeft geen Access-Control-Allow-Origin. Wat klopt er?
Geen browser, geen CORS
Alles hierboven is een belofte die browsers nakomen. wire.py doet zo’n belofte niet. Het stuurt de bytes die je typt en drukt elke byte af die terugkomt, welke headers het antwoord ook heeft. Dat doet pl_sec.py ook, en elk programma dat iemand met een
Een header Access-Control-Allow-Origin vraagt alleen iets van browsers. Als je hem weglaat, verberg je niets voor een programma dat geen browser is. Onthoud dat in dit hoofdstuk: wat geheim of onveranderd moet blijven, heeft nog steeds de controles van hoofdstuk 4 tot en met 8 nodig, de Origin.
wire.py stuurt GET /about, en het antwoord heeft geen CORS-header. Kan het de body lezen?
Dat is de hele uitwisseling voor een gewone GET. Twee gevallen komen later in dit hoofdstuk: een verzoek waar een browser eerst naar vraagt voordat hij het verstuurt, en een verzoek dat een