0%

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 . Was daraus folgt, weißt du aus Lektion 4 von Kapitel 8: Die Anfrage wird gesendet, der Server antwortet, und die hält die Antwort von der Seite fern. Diese Regel hat ana vor den Seiten des Nachbarn geschützt. Hier hält sie eine Seite auf, die du selbst geschrieben hast.

Der Server darf Ja sagen

Die Same-Origin-Policy hat eine , und der Server bestimmt über sie. Eine Antwort darf einen Header tragen, der einen Origin nennt:

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 , kurz für Cross-Origin Resource Sharing. Für ein schlichtes GET braucht sie vier Schritte.

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
  1. Das Skript der Seite bittet seinen Browser um die Anfrage.

  2. Der Browser sendet sie. Weil die Anfrage an einen anderen Origin geht, fügt der Browser einen Header Origin mit dem Origin der Seite hinzu. Die Seite kann diesen Header nicht ändern.

  3. Der Server antwortet wie immer. Wenn er will, fügt er Access-Control-Allow-Origin hinzu.

  4. 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- in der Form, die dein Server zurückgibt, und die Prüfung, die ein Browser macht. Führe ihn aus. Nimm dann den Header aus dem Dictionary, ändere ihn in "*" oder ändere PAGE in "https://notes.reading.example", und führe ihn jedes Mal erneut aus.

Try it

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 schreibt.

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 , das Token, den Eigentümer eines Buchs und die Prüfung von 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 trägt. In der nächsten Lektion schreibst du beide Hälften des einfachen Falls, die Antwort des Servers und die Prüfung des Browsers.