Umstieg auf HTTPs
lima-city → Forum → Programmiersprachen → PHP, MySQL & .htaccess
anzeigen
array
aufruf
aufrufen
bedingung
benutzer
besucher
browser
code
datei
fehler
http
inhalt
problem
schleife
server
url
verbindung
warnung
webseite
-
Es gibt bei Lima-City ja seit einiger Zeit die Funktion, dass man Webseiten auch einfach per `https://` aufrufen kann. Ich habe mich über die Vorstellung dieser Funktion sehr gefreut und beschlossen, sie nicht nur einfach "`im Hintergrund aktiv zu wissen"', sondern auch den Webseitenbesuchern vorzuschlagen, auf die HTTPs-Variante zu wechseln.
Meine erste Idee war dabei, einfach direkt und immer beim Aufruf der HTTP-Seite auf HTTPS umzuleiten -- dafür finden sich online zahlreiche Anleitungen, die aber meistens unberücksichtigt lassen, dass es zwecks Abwärtskompatibilität gut wäre, wenn man die Seite "`notfalls"' auch per HTTP erreichen könnte -- wenn alles auf HTTPS umleitet, geht das jedoch nicht mehr.
Statt jetzt eine eigene Logik mit einem Formular für den Benutzer zur Entscheidung "`HTTPS ja oder nein"' zu entwickeln, habe ich mich für eine andere Variante entschieden: Ich will einfach auf meiner Webseite beim Aufruf über HTTP eine auffällige Warnung anzeigen lassen und dem Benutzer vorschlagen, aus eigener Kraft auf HTTPS zu wechseln.
Dazu habe ich folgenden Code in meine Webseite eingefügt (an der Stelle, wo die Warnung später erscheinen soll)<!-- <?php include "&d5man_pre;internal/https_warn.php"; ?> -->
(das Entity &d5man_pre; wird natürlich noch vor dem FTP-Upload durch den korrekten Pfad ersetzt).
Die interessantere Datei `https_warn.php` enthält dann folgendes:<?php if(((!isset($_SERVER["HTTPS"]) || $_SERVER["HTTPS"] !== "on"))) { echo(" -"."-".">\n"); ?> <div id="https_warning"> ⚠ Sie betrachten diese Seite über eine unverschlüsselte HTTP Verbindung. <a href="<?php echo(htmlspecialchars( "https://masysma.lima-city.de". $_SERVER["PHP_SELF"])); ?>">Empfehlung: Diese Seite verschlüsselt über HTTPS aufrufen.</a> </div> <hr/> <?php echo("\t\t<"."!"."-"."- "); } ?>
(Vom komischen Zusammensetzen der Strings und den XML-Kommentaren nicht abschrecken lassen -- das liegt daran, dass die Seite auch offline funktioneren soll und dass der Code erst nachrtäglich in eine Datei ausgelagert wurde).
Prinzipiell (bei mir auf einem lokalen Testsystem) funktioniert das auch, wenn ich die Seite allerdings über Lima-City aufrufe, erhalte ich auch die Warnung auf der HTTP Seite korrekt, wenn ich dann den Link anklicke, ist sie immernoch da. Wenn ich dann die URL testweise mit einem beliebigen Parameter aufrufe, verschwindet die Warnung. Ich vermute, das liegt an einem Cache? Der Browser ist jedenfalls nicht Schuld, das Problem tritt in Chromium und Iceweasel gleichermaßen auf.
(Zum Testen einfach meine Seite aufrufen -- der Code steht genauso online, wie hier beschrieben).
Soll ich als Workaround einfach an den Link einen "`überflüssigen"' Parameter anhängen, oder habe ich einen Fehler in meinem PHP? Kann man das Problem anders lösen (oder ist es bereits bekannt und wird schon gelöst? -- Ich hatte kurz mit dem Gedanken gespielt, das hier ins Lima-City Community Support-Forum zu schreiben, mich dann aber dagegen entschieden).
Ich hoffe ihr könnt mir weiterhelfen.
-
Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!
lima-city: Gratis werbefreier Webspace für deine eigene Homepage
-
!== gibt es nicht als gültigen Operator.
!= müsste es lauten.
Allerdings würde ich die if clause abändern, if(empty($_SERVER['HTTPS'])){ deckt alles ab, denn nur wenn https auch aktiviert ist, ist die Variable gesetzt. Dann ist es auch egal welchen Inhalt sie hat.
Das beschreibt auch die PHP Dokumentation:Wird auf einen nicht-leeren Wert gesetzt, wenn das Skript via HTTPS aufgerufen wurde.
Weiterhin ist die Frage, wieso du 3 Klammern zum öffnen und schließen der if clause nutzt. Verstehe ich nicht, da reicht auch eine am Anfang und eine am Ende. -
Oder doch deine Browser?
Im Firefox funktioniert es tadellos.
Edit:
Aber warum SSL. Deine Besucher geben ja keine Nutzerdaten ein. Ist also nur eine Verschwendung von Ressourcen. Denn SSL verbraucht Rechenleistung seitens des Servers und des Endnutzers.
Beitrag zuletzt geändert: 19.10.2015 15:30:11 von all-in1 -
!== gibt es nicht als gültigen Operator.
vgl. http://php.net/manual/de/language.operators.comparison.php
!= müsste es lauten.
Allerdings würde ich die if clause abändern, if(empty($_SERVER['HTTPS'])){ deckt alles ab, denn nur wenn https auch aktiviert ist, ist die Variable gesetzt. Dann ist es auch egal welchen Inhalt sie hat.
Die drei Klammern sind zugegebenermaßen überflüssig :),
Das beschreibt auch die PHP Dokumentation:
Wird auf einen nicht-leeren Wert gesetzt, wenn das Skript via HTTPS aufgerufen wurde.
Weiterhin ist die Frage, wieso du 3 Klammern zum öffnen und schließen der if clause nutzt. Verstehe ich nicht, da reicht auch eine am Anfang und eine am Ende.
das mit dem `!== "on"` hat jedoch einen gewissen Sinn: http://stackoverflow.com/questions/5100189/use-php-to-check-if-page-was-accessed-with-ssl. Kurz gefasst: Nicht alle Systeme, die PHP unterstützen, halten sich auch an diese Spezifikation. Gewisse Server setzen das Feld wohl einfach auf `no`, wenn kein HTTPs-Aufruf stattfindet. Da ich natürlich nicht nur für Lima-City, sondern für maximale Kompatibilität entwickle, ist es mir wichtig, die "`sicherste"' Variante zu verwenden :)
Oder doch deine Browser?
Ich kann mir nicht vorstellen, wie es am Browser liegen könnte, aber ich habe es mal mit einem Firefox 31 (zugegebenermaßen, der ist alt, aber inwiefern sollte sich da was neuern? / ... auch mit Firefox 41.0.2 tritt das Problem gleichermaßen auf) in einer Windows-VM getestet und das gleiche Problem gesehen:
Im Firefox funktioniert es tadellos.
1. Aufruf der Startseite mit HTTP
2. Warnung erscheint
3. Klick auf den Link in der Warnung
4. URL mit HTTPS korrekt angezeigt, aber Warnung immernoch vorhanden
Ich bin mir ziemlich sicher, dass es ein Cache-Problem ist, welches nicht lokal in meinem Browser auftritt (Caches testweise deaktivieren liefert das gleiche Ergebnis). Ich vermute, dass es irgendwo zwischen meinem lokalen Computer und dem remote liegenden PHP-Script einen Cache gibt, der immer das zuletzt ausgegebene Ergebnis liefert -- unabhängig vom Protokoll. Auf diese Weise wird nach einem Aufruf via HTTP einfach das gleiche Ergebnis per HTTPS übermittelt. Die umgekehrte Richtung lässt sich mit einem ähnlichen Vorgehen wie oben beschrieben ebenfalls beschreiten: Ruft man eine Seite, die gerade nicht in diesem ominösen Cache ist per HTTPS auf, erscheint die Warnung nicht. Ruft man sie dann per HTTP auf, erscheint die Warnung auch nicht!
Edit:
Deshalb habe ich dem auch nur untergeordnete Priorität eingeordnet und will HTTPs auf jeden Fall optional lassen (weniger wegen der Rechenleistung, mehr wegen der Kompatiblität). Es gibt verschiedene Gründe warum mich auf einer komplett öffentlich zugänglichen Seite überhaupt HTTPs interessiert:
Aber warum SSL. Deine Besucher geben ja keine Nutzerdaten ein. Ist also nur eine Verschwendung von Ressourcen. Denn SSL verbraucht Rechenleistung seitens des Servers und des Endnutzers.
1. Wenn ich es richtig in Erinnerung habe, bevorzugt Google Seiten, die verschlüsselt aufgerufen werden können.
2. Ich sezte mich generell für Verschlüsselung ein, ob es sich nun um verschlüsselnswerte Inhalte handelt, oder nicht. Hintergedanke ist folgendes: Wenn alles verschlüsselt wird, fallen geheimhaltungswerte Daten nicht auf -- wenn nur Wichtiges verschlüsselt wird, dann ist es umso wahrscheinlicher, dass sich ein Angriff lohnt.
3. HTTPS verschlüsselt nicht nur auf einfache Weise, sondern stellt auf genauso einfache Weise auch die Integrität der Daten wärend der Übertragung sicher. Ich kann also im Idealfall davon ausgehen, dass meine Seite per HTTPS aufgerufen genauso beim Benutzer ankommt, wie der Server sie verschickt hat. Zukünftige Aktionen seitens Providern oder Proxies, die Inhalte blockieren oder zusätzlich Werbung einfügen oder einfache Angriffe, die meine Seite um Spam erweitern oder ähnliche Änderungen am Seiteninhalt werden damit erschwert.
Das sind alles keine extrem wichtigen Gründe, aber dennoch genug, um für mich den Ausschlag zu geben, HTTPS (gerade wo es jetzt einfach für jeden verfügbar ist) standardmäßig verwenden zu wollen.
---
Edit: Ich habe jetzt einen kleinen Workaround eingebaut, der das Problem etwas besser versteckt (entsprechend ist der Fehler schwieriger zu reproduzieren):
Ich verwende jetzt folgenden Code<?php if(!isset($_SERVER["HTTPS"]) || $_SERVER["HTTPS"] !== "on") { echo(" -->\n"); ?> <div id="https_warning"> ⚠ Sie betrachten diese Seite über eine unverschlüsselte HTTP Verbindung. <a href="<?php echo(htmlspecialchars( "https://masysma.lima-city.de". $_SERVER["PHP_SELF"]."?moved_to_https")); ?>">Empfehlung: Diese Seite verschlüsselt über HTTPS aufrufen.</a> </div> <hr/> <?php echo("\t\t<!-- "); } ?>
Insbesondere die Änderung in Zeile 8 ist relevant: Ich hänge beim Umleiten auf HTTPs noch einen Parameter an, sodass der Cache verworfen wird und die Seite neu generiert wird.
Reproduktion des Fehlers geht wie folgt:
1. Aufruf der Seite http://masysma.lima-city.de/31/web_main.xhtml?aaaa
(Für `aaaa` einen anderen beliebigen Parameter einsetzen und merken)
2. Klick auf den HTTPs-Umleitungslink (die Nachricht verschwindet wegen dem Workaround)
3. Ändern des Parameters `moved_to_https` in `aaaa` (bzw. einen anderen Parameternamen)
-> Trotz HTTPS-Aufruf erscheint die Nachricht man würde nicht über HTTPs kommen.
---
Nochmal Edit :)
Ich habe jetzt folgenden Code onlinegestellt<?php echo(uniqid("ma_rnd_cache_workaround_", true)); if(!isset($_SERVER["HTTPS"]) || $_SERVER["HTTPS"] !== "on") { echo(" -->\n"); ?> <div id="https_warning"> ⚠ Sie betrachten diese Seite über eine unverschlüsselte HTTP Verbindung. <a href="<?php echo(htmlspecialchars( "https://masysma.lima-city.de". $_SERVER["PHP_SELF"]."?moved_to_https")); ?>">Empfehlung: Diese Seite verschlüsselt über HTTPS aufrufen.</a> </div> <hr/> <?php echo("\t\t<!-- EHTTPS"); } ?>
Damit tritt das Problem immernoch auf und ich kann im Quelltext der "`fehlerhaft"' gelieferten Seiten die gleiche `uniqid` finden, wie in der davor über https gelieferten Seite.
Beitrag zuletzt geändert: 19.10.2015 23:16:41 von masysma -
Es muss aber anstelle von
!==
heissen.!=
Dann ist da ein kleiner gedanklicher Fehler.
Je nach dem was der Server sagt.
Also wenn SSL empty dann Schleife
Oder wenn SSL auf off dann Schleife
In deinem Fall muss also wenn SSL Aufruf erfolgt https in der Uri stehen und der Server muss SSL auf on stellen.
Laut deinem Link ist letzteres aber nur auf einem IIS der Fall und somit muss er die Schleife zwangsläufig durchlaufen.
Leider kann ich das ganze nicht wirklich mal testen, da ich auf Premium bin und kein SSL Zertifikat besitze.
Da aber bei dir irgendwann die Schleife (also nach einem Reload) nicht durchlaufen wird, wird einer der beiden Fälle erst wahr, wenn einmal eine SSL Verbindung bestanden hat. hängt damit zusammen, wie in der httpd conf die Einträge abgearbeitet werden. Bzw. in einer der ganzen phpVersions Dateien.
Google ist es völlig egal, ob eine Webseite mit https oder mit http aufgerufen wird. Du hast jetzt aber ein Problem, denn du hast jetzt doppelten Content. Und das ist weit aus schlechter.
Dann sind deine Inhalte so uninteressant, dass sich ein Hacker da wohl keine Mühe machen wird. Und da deine Seite auch nicht zu den TOP 100.000 gehört ist ein Angriff sehr unwahrscheinlich. Es gäbe ja nicht mal Userdaten, die man holen könnte.
Zugegeben, der letzte Punkt, ist der einzig wirklich interessante. Nur weiss ich nicht, ob es schon ISP's gibt, die sich mit Werbung finanzieren. Aber auch dafür gibt es schon seitens Google Lösungen. -
all-in1 schrieb:
Ich verstehe das nicht ganz. Einerseits befindet sich im relevanten (und hier geposteten) Codeabschnitt keine Schleife? Andererseits habe ich die Bedingung `!isset($_SERVER["HTTPS"]) || $_SERVER["HTTPS"] !== "on"` so aufgestellt, dass sie in Worten lautet "`Falls der Key HTTPS im Array $_SERVER nicht gesetzt ist (IOW: kein HTTPS Aufruf stattfindet) oder der Wert zum Key HTTPS nicht auf "on" steht (für den Fall, dass der Key gesetzt, aber nicht "on" ist), dann wird die Warnung ausgegeben"'
Es muss aber anstelle von!==
heissen.!=
Dann ist da ein kleiner gedanklicher Fehler.
Je nach dem was der Server sagt.
Also wenn SSL empty dann Schleife
Oder wenn SSL auf off dann Schleife
In deinem Fall muss also wenn SSL Aufruf erfolgt https in der Uri stehen und der Server muss SSL auf on stellen.
Laut deinem Link ist letzteres aber nur auf einem IIS der Fall und somit muss er die Schleife zwangsläufig durchlaufen.
Leider kann ich das ganze nicht wirklich mal testen, da ich auf Premium bin und kein SSL Zertifikat besitze.
Das heißt, ich könnte das Problem durch Anpassung meines Scriptes beheben? Wenn ja, wie?
Da aber bei dir irgendwann die Schleife (also nach einem Reload) nicht durchlaufen wird, wird einer der beiden Fälle erst wahr, wenn einmal eine SSL Verbindung bestanden hat. hängt damit zusammen, wie in der httpd conf die Einträge abgearbeitet werden. Bzw. in einer der ganzen phpVersions Dateien.
Google ist es völlig egal, ob eine Webseite mit https oder mit http aufgerufen wird.
http://googlewebmastercentral.blogspot.de/2014/08/https-as-ranking-signal.html
Du hast jetzt aber ein Problem, denn du hast jetzt doppelten Content. Und das ist weit aus schlechter.
Das stimmt -- und danke für den Hinweis :) . Ich werde das aber -- sollte sich das Problem mit dem falsch angezeigten Hinweis irgendwie lösen lassen, beheben/lindern, indem ich ein Meta-Tag mit Verweis auf die "`kanonische Seite"' erzeuge, vgl. https://support.google.com/webmasters/answer/139066?hl=en
Beitrag zuletzt geändert: 20.10.2015 20:43:30 von masysma -
Ich verstehe das nicht ganz. Einerseits befindet sich im relevanten (und hier geposteten) Codeabschnitt keine Schleife? Andererseits habe ich die Bedingung `!isset($_SERVER["HTTPS"]) || $_SERVER["HTTPS"] !== "on"` so aufgestellt, dass sie in Worten lautet "`Falls der Key HTTPS im Array $_SERVER nicht gesetzt ist (IOW: kein HTTPS Aufruf stattfindet) oder der Wert zum Key HTTPS nicht auf "on" steht (für den Fall, dass der Key gesetzt, aber nicht "on" ist), dann wird die Warnung ausgegeben"'
Ist eine if Anweisung keine Schleife?
dir wird die Warnung ausgegeben, wenn https im $_Server Array nicht gesetzt ist, wobei es egal ist ob es on oder off ist.
Ebenfalls wird die Warnung ausgegeben, wenn https gesetzt ist, aber es auf off ist.
Diese Möglichkeiten muss du also einzeln in einer if Schleife/ Bedingung auffangen. -
all-in1 schrieb:
Hmm... für mich beinhaltet "`Schleife"' immer eine Wiederholung, häufig umgesetzt durch eine Rücksprungaddresse. Beim `if` geht es dagegen doch eher darum, eine Verzweigung (zwei Sprünge typischerweise beide "`nach vorne"') oder zumindest um ein Überspringen (ein Sprung nach vorne). Es sind also beides Anweisungen, die eine Bedingung erwarten... aber das, was sie dann tun ist nicht nur von der Bedingung abhängig, sondern auch davon, ob man eine Schleife oder ein `if` verwendet. :)
Ist eine if Anweisung keine Schleife?
dir wird die Warnung ausgegeben, wenn https im $_Server Array nicht gesetzt ist, wobei es egal ist ob es on oder off ist.
Das ergibt doch eine gute Logik, an der man festmachen kann, ob die Warnung angezeigt werden soll: Es sollen die Benutzer gewarnt werden, die per HTTP kommen -- bei denen also entweder gar kein HTTPS im $_SERVER Array vorkommt oder bei denen der zugehörige Wert off ist (das das natürlich nicht am Benutzer, sondern am Server hängt ist dafür doch irrelevant, oder?). Also ist meine Bedingung richtig formuliert?
Ebenfalls wird die Warnung ausgegeben, wenn https gesetzt ist, aber es auf off ist.
Außerdem "`wenn https im $_SERVER Array nicht gesetzt ist, wobei es egal ist, ob es on oder off ist"' -- wenn es nicht gesetzt ist, kann man ja überhaupt keine Aussagen über den Wert machen. Also verkürzt sich das zu "`wenn es nicht gesetzt ist"' (man also davon ausgeht, dass der Server HTTP erkennt, weil bei HTTPS darin ein Wert sein müsste)?
Diese Möglichkeiten muss du also einzeln in einer if Schleife/ Bedingung auffangen.
Ich will ja für beide Situationen effektiv das Gleiche machen, da ich davon ausgehe, dass der zweite Fall nur bei bestimmten Servern auftritt und dann aber das Gleiche signalisiert, wie der erste Fall auf "`gewöhnlichen"' Servern. -
Das du es für die Besucher, die http gewählt haben anzeigen lassen möchtest ist schon klar, aber das war doch gar nicht mehr das Problem?
Dein Problem ist doch, dass du es nicht mehr anzeigen lassen möchtest, wenn https gewählt ist. Und dafür musst du dann deine Bedingung etwas anders formulieren. Es ist manchmal sehr schwierig alles abzudecken. Manchmal macht es mehr Sinn, nur seinen Fall abzudecken. -
all-in1 schrieb:
Naja, mein Problem ist, dass da ein unsichtbarer Cache dazwischen steht, der immer das ausgibt, was er zuletzt auch ausgegeben hat -- unabhängig vom Protokoll. Das heißt: Ruft man die Seite per HTTPS auf und sieht die Warnung nicht und stellt dann die URL auf `http` um, erscheint die Warnung auch nicht!
Das du es für die Besucher, die http gewählt haben anzeigen lassen möchtest ist schon klar, aber das war doch gar nicht mehr das Problem?
Dein Problem ist doch, dass du es nicht mehr anzeigen lassen möchtest, wenn https gewählt ist. Und dafür musst du dann deine Bedingung etwas anders formulieren. Es ist manchmal sehr schwierig alles abzudecken. Manchmal macht es mehr Sinn, nur seinen Fall abzudecken.
Ich habe jetzt den zweiten Teil der Bedingung testweise gestrichen und bekomme immer noch das gleiche Ergebnis.
Wenn es keine Lösung gibt, werde ich nochmal versuchen, ob man mit passenden Headers den Cache deaktiveren kann und andernfalls werde ich die Warnung eben wieder herausnehmen. -
Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!
lima-city: Gratis werbefreier Webspace für deine eigene Homepage