Kapitel 9
CORS
Die Erlaubnis zu lesen
In Kapitel 8 ging es um eine Anfrage, die eine andere Seite nicht stellen können sollte. Dieses Kapitel beginnt mit dem umgekehrten Wunsch.
Die Leseliste bekommt ein zweites Frontend, unter https://app.reading.example. Es ist einer der vier Namen aus Kapitel 8, und es gehört dir. Ein Skript auf seinen Seiten möchte GET https://reading.example/about senden und die Antwort anzeigen.
Die beiden Hosts sind eine Site und zwei
Der Server darf Ja sagen
Die Same-Origin-Policy hat eine
access-control-allow-origin: https://app.reading.example
Mit diesem Header sagt der Server: Eine Seite auf diesem Origin darf diese Antwort lesen. Die Vereinbarung heißt
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
Das Skript der Seite bittet seinen Browser um die Anfrage.
Der Browser sendet sie. Weil die Anfrage an einen anderen Origin geht, fügt der Browser einen Header
Originmit dem Origin der Seite hinzu. Die Seite kann diesen Header nicht ändern.Der Server antwortet wie immer. Wenn er will, fügt er
Access-Control-Allow-Originhinzu.Der Browser sieht sich diesen einen Header an. Er gibt die Antwort nur dann an das Skript weiter, wenn der Header den Origin der Seite nennt oder
*ist, was für jeden Origin steht. In jedem anderen Fall bekommt das Skript nichts.
Sieh dir an, wer in jedem Schritt handelt. Der Server erteilt die Erlaubnis im dritten Schritt. Der Browser setzt sie im vierten durch. Die Seite hat überhaupt kein Mitspracherecht.
Der Header Origin aus dem zweiten Schritt ist der, den dein Server schon liest. In Kapitel 8 hat er ihn benutzt, um ein gefälschtes POST abzulehnen. Jetzt sagt derselbe Header dem Server, welche Seite fragt, damit er dieser Seite mit Namen antworten kann.
Verfolge es
Der nächste Block ist der vierte Schritt: ein Antwort-"*" oder ändere PAGE in "https://notes.reading.example", und führe ihn jedes Mal erneut aus.
Dieser Block ist eine Skizze der Regel, und er sendet nichts. In Lektion 2 schreibst du die echte Prüfung in mini_browser.py.
Wer entscheidet bei jeder Anfrage, ob eine Seite eine Antwort von einem anderen Origin lesen darf?
Was der Server getan hat, bevor der Browser entschied
Beim vierten Schritt ist der Server fertig. Er hat die Anfrage empfangen, handle() ausgeführt und die ganze Antwort gesendet. Wenn der Browser das Lesen verweigert, wird nichts zurückgenommen. Die Antwort ist angekommen, und sie wurde einem Skript vorenthalten.
Ein fehlender Header macht also nie etwas rückgängig. Wenn die Anfrage auf dem Server etwas geändert hat, ist die Änderung gemacht. Das ist noch einmal die Lehre aus Kapitel 8: Das Lesen bewacht der Browser, und eine Anfrage, die etwas ändert, hat das getan, bevor irgendein Header angesehen wird.
Eine Seite auf einem anderen Origin sendet ein Formular ab, und der Server führt es aus. Die Antwort hat kein Access-Control-Allow-Origin. Was stimmt?
Kein Browser, kein CORS
Alles oben ist ein Versprechen, das Browser halten. wire.py hält kein solches Versprechen. Es sendet die Bytes, die du tippst, und gibt jedes Byte aus, das zurückkommt, egal welche Header die Antwort hat. Das Gleiche tut pl_sec.py, und das Gleiche tut jedes Programm, das jemand mit einem
Ein Header Access-Control-Allow-Origin verlangt nur etwas von Browsern. Ihn wegzulassen verbirgt nichts vor einem Programm, das kein Browser ist. Behalte das in diesem Kapitel im Kopf: Was geheim oder unverändert bleiben muss, braucht weiterhin die Prüfungen der Kapitel 4 bis 8, die Origin.
wire.py sendet GET /about, und die Antwort hat keinen CORS-Header. Kann es den Body lesen?
Das ist der ganze Austausch für ein schlichtes GET. Zwei Fälle bleiben für später in diesem Kapitel: eine Anfrage, nach der ein Browser fragt, bevor er sie sendet, und eine Anfrage, die ein