Linuchs: Ajax: HTTP verweigert Aufruf von HTTPS

problematische Seite

Moin,

seit einer Woche beschäftige ich mich mit der Umstellung. Die problematische Seite kann wahlweise mit http oder https aufgerufen werden.

Wenn mit https, werden sogar Bilder nicht geladen (oder nur nicht gezeigt?), die per http aufgerufen werden. Da waren einige Korrekturen nötig.

Andersrum gab es zunächst keine Probleme. Nachdem die Bild-Aufrufe auf https umgestellt waren, durften sie auch von http gerufen werden.

Doch was ist das: Die http-Seite darf per Ajax keine Information nachladen, die mit https aufgerufen wird. Es geht um die Veranstaltung „zuletzt gelesen“.

Fehlermeldung der Konsole:

Quellübergreifende (Cross-Origin) Anfrage blockiert: Die Gleiche-Quelle-Regel verbietet das Lesen der externen Ressource auf https://remso.eu/ajax/events_zuletzt_gelesen.php?TID=&lg1=de&lg2=de. (Grund: CORS-Kopfzeile 'Access-Control-Allow-Origin' fehlt).

Ich kenne noch nicht alle Probleme, die mit einer Umstellung auf https verbunden sind, deshalb möchte ich noch ein paar Wochen beide Möglichkeiten.

Wie kann ich dem Fehler begegnen?

Kann Javascript ermitteln, ob es sich im http oder https Bereich bewegt?

Was ist eine CORS-Kopfzeile? Muss ich die dem Ajax-Aufruf voranstellen?

Kann ich selbst bestimmen, dass ein http- Aufruf als https ausgeliefert wird, etwa in der .htaccess?

fragt Linuchs

  1. problematische Seite

    Tach!

    Wenn mit https, werden sogar Bilder nicht geladen (oder nur nicht gezeigt?), die per http aufgerufen werden.

    Was da konkre der Fall ist, offenbaren die Entwicklertools des Browsers, nicht zuletzt die Konsole mit ihren Fehlermmeldungen.

    Andersrum gab es zunächst keine Probleme. Nachdem die Bild-Aufrufe auf https umgestellt waren, durften sie auch von http gerufen werden.

    Ja, gesichert übertragene Elemente dürfen immer in ungesichert übertragenen Dokumenten angezeigt/eingebunden werden. Dabei verringert sich ja die sowieso schon bei der Übertagung nicht vorhandene Sicherheit der HTTP-Ressource nicht.

    Doch was ist das: Die http-Seite darf per Ajax keine Information nachladen, die mit https aufgerufen wird. Es geht um die Veranstaltung „zuletzt gelesen“.

    Fehlermeldung der Konsole:

    Quellübergreifende (Cross-Origin) Anfrage blockiert: Die Gleiche-Quelle-Regel verbietet das Lesen der externen Ressource auf https://remso.eu/ajax/events_zuletzt_gelesen.php?TID=&lg1=de&lg2=de. (Grund: CORS-Kopfzeile 'Access-Control-Allow-Origin' fehlt).

    https://example.com und http://example.com sind unterschiedliche Quellen, da weigert sich der Browser erstmal.

    Wie kann ich dem Fehler begegnen?

    Kann Javascript ermitteln, ob es sich im http oder https Bereich bewegt?

    Nein, aber man kann protokollrelative Verweise notieren //example.com. Damit nimmt der Browser das Protokoll der einbettenden Ressource.

    Was ist eine CORS-Kopfzeile? Muss ich die dem Ajax-Aufruf voranstellen?

    CORS-Header zu setzen kann auch bereits reichen. Damit erlaubt der Server dem Browser, von wo aus Scripts nachgeladen werden dürfen.

    Beispielsweise zeigt ein Dokument mit dem HTTP-Header Access-Control-Allow-Origin: *dem Browser an, dass er von allen Quellen aus Ressourcen nachladen darf. Statt * kann da auch sowas wie https://example.com stehen.

    dedlfix.

    1. problematische Seite

      Hallo dedlfix,

      Nein, aber man kann protokollrelative Verweise notieren //example.com. Damit nimmt der Browser das Protokoll der einbettenden Ressource.

      So einfach ist das. Danke dir.

    2. problematische Seite

      Tach!

      Was ist eine CORS-Kopfzeile? Muss ich die dem Ajax-Aufruf voranstellen?

      CORS-Header zu setzen kann auch bereits reichen. Damit erlaubt der Server dem Browser, von wo aus Scripts nachgeladen werden dürfen.

      Beispielsweise zeigt ein Dokument mit dem HTTP-Header Access-Control-Allow-Origin: *dem Browser an, dass er von allen Quellen aus Ressourcen nachladen darf. Statt * kann da auch sowas wie https://example.com stehen.

      Hier muss ich mich korrigieren. Es ist nicht das Dokument, dass erzählt, wo es überall hingreifen darf. Es ist stattdessen die einzubettende Ressource, die dem Browser erzählt, von wo aus sie eingebunden werden darf.

      Eine Ajax-Response muss den Header Access-Control-Allow-Origin setzen und dabei die Domain (plus Protokoll) der Seite(n) angeben, die darauf zugreifen dürfen. Moderne Browser halten sich daran und verweigern auch gern mal den Zugriff komplett, wenn der Header fehlt. Oder sie liefern nur die Header an das aufrufende Script zurück und verwerfen den Inhalt. Statt einer Adresse (oder einer Liste) kann auch * angegeben werden, wenn von überall darauf zugegriffen werden darf, wenn also die Daten nicht nur für die eine Domain (oder die Liste) bestimmt sind.

      dedlfix.

  2. problematische Seite

    Hallo Linuchs,

    der Origin wird durch Protokoll, Domain und Port bestimmt. D.h. http://example.org und https://example.org sind unterschiedliche Origins und der Browser bockt.

    So richtig durchdrungen habe ich das auch nicht, vor allem was „preflighted requests“ angeht, aber hier steht eine Menge zum Thema.

    Rolf

    --
    sumpsi - posui - clusi
    1. problematische Seite

      Tach!

      So richtig durchdrungen habe ich das auch nicht, vor allem was „preflighted requests“ angeht, aber hier steht eine Menge zum Thema.

      Mit dem Preflight Request fragt der Browser erstmal die Header der einzubindenden Ressource ab, um nach Access-Control-Allow-Origin und seinen Kumpanen Ausschau zu halten. Dann entscheidet er, ob er den eigentlichen Request startet oder auch nicht.

      Ansonsten ist CORS eine "Du darfst mich (nicht) einbinden"-Geschichte. Man sollte sie verstanden haben, weil sonst die Browser nicht mitspielen, wenn die Header bei Cross-Origin-Zugriffen fehlen.

      Beispiel:

      Eine öffentliche API setzt keinen Access-Control-Allow-Origin: *. Dann kann man zwar mit selbst (z.B. serverseitig) erzeugten Requests darauf zugreifen, weil man dabei ja diesen Header nicht zu beachten braucht. Die Daten werden (bei richtigem Request, also nicht dem Preflight) problemlos ausgeliefert. Setzt man allerdings im Browser einen XMLHttpRequest oder fetch() ab, muss der Header gesetz sein, sonst sagt der Browser: "Nein, das hol ich nicht oder geb dir keine Daten." Keine Daten zu geben ist der Fall, wenn man fetch() mit mode: 'no-cors' losschickt. Da setzt er zwar den eigentlichen Request ab, behält aber die Daten für sich.

      dedlfix.

      1. problematische Seite

        Hallo dedlfix,

        was ich nicht kapiere, ist, wer die Header setzen muss. Und was der Spaß überhaupt soll.

        Site A liefert Script aus, das AJAX Zugriffe auf Site B machen weil. Muss der Server von A seinem eigenen Script per Header gestatten, sich an Site B zu wenden? Wozu? Er kann doch gestatten was er will und jeglicher Schutz ist vorbei. Oder muss Site B Anfragen von Scripten von Site A erlauben? Woran erkennt sie dann zuverlässig Scripte von A?

        Das setzt doch immer eine vertrauenswürdige Kontrollinstanz voraus, damit es überhaupt funktioniert.

        Außerhalb vom Browser fehlt die, und wer Böses will, ist ja frei. keinen Browser zu nutzen. Wo ist also der Sinn des ganzen?

        Rolf

        --
        sumpsi - posui - clusi
        1. problematische Seite

          Tach!

          was ich nicht kapiere, ist, wer die Header setzen muss.

          Site A liefert Script aus, das AJAX Zugriffe auf Site B machen weil. Muss der Server von A seinem eigenen Script per Header gestatten, sich an Site B zu wenden? Wozu? Er kann doch gestatten was er will und jeglicher Schutz ist vorbei. Oder muss Site B Anfragen von Scripten von Site A erlauben?

          Ersteres nicht. B muss dem anfragenden Browser erzählen, ob Zugriffe von unter A laufenden Dokumenten oder * erlaubt sind.

          Dabei gilt: Nicht nur Server A hat ein oder mehrere Dokumente ausgeliefert, auch nachgeladenen Scripte laufen unter A, egal wo sie herkommen.

          Woran erkennt sie dann zuverlässig Scripte von A?

          Am Origin-Header, den der Browser mitsendet. Meist hat man aber fest eingestellt, was in Access-Control-Allow-Origin und Co. geantwortet werden soll, und was in Origin steht ist irrelevant.

          Das Ganze ist ja kein Authorization-Feature, sondern eins für die Browser-Sicherheit.

          Und was der Spaß überhaupt soll.

          Schutz der unbedarften Anwender mit Standard-Browsern.

          Das setzt doch immer eine vertrauenswürdige Kontrollinstanz voraus, damit es überhaupt funktioniert.

          Server A mit HTTPS. Und Server B, der dem Browser sagt, ob das Script von A zugreifen darf.

          Außerhalb vom Browser fehlt die, und wer Böses will, ist ja frei. keinen Browser zu nutzen. Wo ist also der Sinn des ganzen?

          Wenn du den Anwender dazu bringen kannst, was anderes als den Standard-Browser zu verwenden, hast du sowieso schon gewonnen.

          dedlfix.