it-swarm.com.de

Wie Sie herausfinden, ob Sie HTTPS ohne $ _SERVER ['HTTPS'] verwenden?

Ich habe viele Online-Tutorials gesehen, die besagen, dass Sie $_SERVER['HTTPS'] überprüfen müssen, ob die Verbindung des Servers mit HTTPS gesichert ist. Mein Problem ist, dass $_SERVER['HTTPS'] auf einigen Servern, die ich verwende, eine undefinierte Variable ist, die zu einem Fehler führt. Gibt es eine andere Variable, die ich überprüfen kann, die immer definiert werden sollte?

Um klar zu sein, verwende ich derzeit diesen Code, um zu ermitteln, ob es sich um eine HTTPS-Verbindung handelt:

if(isset($_SERVER['HTTPS'])) {
    if ($_SERVER['HTTPS'] == "on") {
        $secure_connection = true;
    }
}
172
Tyler Carter

Chacha gemäß der Dokumentation PHP: "Setzen Sie einen nicht leeren Wert, wenn das Skript über das HTTPS-Protokoll abgefragt wurde." Daher wird Ihre if-Anweisung dort in vielen Fällen falsch zurückgegeben, wenn HTTPS tatsächlich aktiviert ist. Stellen Sie sicher, dass $_SERVER['HTTPS'] vorhanden ist und nicht leer ist. In den Fällen, in denen HTTPS für einen bestimmten Server nicht richtig eingestellt ist, können Sie prüfen, ob $_SERVER['SERVER_PORT'] == 443.

Beachten Sie jedoch, dass einige Server $_SERVER['HTTPS'] auch auf einen nicht leeren Wert setzen. Überprüfen Sie daher auch diese Variable.

Referenz: Dokumentation für $_SERVER und $HTTP_SERVER_VARS [veraltet]

80
hobodave

Dies sollte immer funktionieren, auch wenn $_SERVER['HTTPS'] nicht definiert ist:

function isSecure() {
  return
    (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off')
    || $_SERVER['SERVER_PORT'] == 443;
}

Der Code ist mit IIS kompatibel.

Aus der PHP.net-Dokumentation und den Benutzerkommentaren :

1) Stellen Sie einen nicht leeren Wert ein, wenn das Skript über das HTTPS-Protokoll abgefragt wurde.

2) Beachten Sie, dass bei Verwendung von ISAPI mit IIS der Wert "aus" ist, wenn die Anforderung nicht über das HTTPS-Protokoll gestellt wurde. (Dasselbe Verhalten wurde für IIS7 gemeldet, auf dem PHP als Fast-CGI-Anwendung ausgeführt wird).

Auf Apache 1.x-Servern (und fehlerhaften Installationen) wurde $_SERVER['HTTPS'] möglicherweise nicht definiert, selbst wenn die Verbindung sicher ist. Verbindungen auf Port 443 sind zwar nicht garantiert, werden jedoch nach convention wahrscheinlich mit sicheren Sockets verwendet, daher die zusätzliche Portprüfung.

255
Gras Double

Meine Lösung (weil die Standardbedingungen [$ _SERVER ['HTTPS'] == 'on'] nicht auf Servern hinter einem Load Balancer funktionieren) ist:

$isSecure = false;
if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') {
    $isSecure = true;
}
elseif (!empty($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https' || !empty($_SERVER['HTTP_X_FORWARDED_SSL']) && $_SERVER['HTTP_X_FORWARDED_SSL'] == 'on') {
    $isSecure = true;
}
$REQUEST_PROTOCOL = $isSecure ? 'https' : 'http';

HTTP_X_FORWARDED_PROTO: Ein de facto -Standard zum Identifizieren des Ursprungsprotokolls einer HTTP-Anforderung, da ein Reverse-Proxy (Load Balancer) über HTTP mit einem Webserver kommunizieren kann, auch wenn die Anforderung an den Reverse-Proxy HTTPS ist. http://en.wikipedia.org/wiki/List_of_HTTP_header_fields#Common_non-standard_request_headers

105
temuraru

Dies funktioniert auch, wenn $_SERVER['HTTPS'] nicht definiert ist 

if( (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off') || $_SERVER['SERVER_PORT'] == 443 ){
    //enable secure connection
}
13
Thamaraiselvam

Ich hatte gerade ein Problem, bei dem ich den Server mit Apache mod_ssl ausführte. Ein phpinfo () und ein var_dump ($ _SERVER) zeigten jedoch, dass PHP immer noch denkt, dass ich an Port 80 bin.

Hier ist mein Workaround für alle mit dem gleichen Problem ....

<VirtualHost *:443>
  SetEnv HTTPS on
  DocumentRoot /var/www/vhost/scratch/content
  ServerName scratch.example.com
</VirtualHost>

Die erwähnenswerte Zeile ist die SetEnv-Zeile. Nach diesem Neustart sollten Sie die HTTPS-Umgebungsvariable haben, von der Sie immer geträumt haben

8
thomas-peter

Wenn Sie Apache verwenden, können Sie immer darauf zählen

$_SERVER["REQUEST_SCHEME"]

um das Schema der angeforderten URL zu überprüfen. Wie in anderen Antworten erwähnt, ist es jedoch ratsam, andere Parameter zu überprüfen, bevor davon ausgegangen wird, dass SSL tatsächlich verwendet wird.

7
Ed de Almeida

Die ECHTE Antwort: Bereit zum Kopieren und Einfügen in ein [config] -Skript

/* configuration settings; X=edit may 10th '11 */
$pv_sslport=443; /* for it might be different, as also Gabriel Sosa stated */
$pv_serverport=80; /* X */
$pv_servername="mysite.com"; /* X */

/* X appended after correction by Michael Kopinsky */
if(!isset($_SERVER["SERVER_NAME"]) || !$_SERVER["SERVER_NAME"]) {
    if(!isset($_ENV["SERVER_NAME"])) {
        getenv("SERVER_NAME");
        // Set to env server_name
        $_SERVER["SERVER_NAME"]=$_ENV["SERVER_NAME"];
    }
}
if(!$_SERVER["SERVER_NAME"]) (
    /* X server name still empty? ... you might set $_SERVER["SERVER_NAME"]=$pv_servername; */
}

if(!isset($_SERVER["SERVER_PORT"]) || !$_SERVER["SERVER_PORT"]) {
    if(!isset($_ENV["SERVER_PORT"])) {
        getenv("SERVER_PORT");
        $_SERVER["SERVER_PORT"]=$_ENV["SERVER_PORT"];
    }
}
if(!$_SERVER["SERVER_PORT"]) (
    /* X server port still empty? ... you might set $_SERVER["SERVER_PORT"]=$pv_serverport; */
}

$pv_URIprotocol = isset($_SERVER["HTTPS"]) ? (($_SERVER["HTTPS"]==="on" || $_SERVER["HTTPS"]===1 || $_SERVER["SERVER_PORT"]===$pv_sslport) ? "https://" : "http://") :  (($_SERVER["SERVER_PORT"]===$pv_sslport) ? "https://" : "http://");

$pv_URIprotocol ist jetzt korrekt und kann verwendet werden. Beispiel $site=$pv_URIprotocol.$_SERVER["SERVER_NAME"]. Natürlich könnte der String auch durch TRUE und FALSE ersetzt werden. PV steht für PortalPress Variable, da es ein direktes Kopieren und Einfügen ist, das immer funktionieren wird. Dieses Stück kann in einem Produktionsskript verwendet werden.

Erstellen Sie meine eigene Funktion aus dem Lesen aller vorherigen Beiträge:

public static function isHttps()
{
    if (array_key_exists("HTTPS", $_SERVER) && 'on' === $_SERVER["HTTPS"]) {
        return true;
    }
    if (array_key_exists("SERVER_PORT", $_SERVER) && 443 === (int)$_SERVER["SERVER_PORT"]) {
        return true;
    }
    if (array_key_exists("HTTP_X_FORWARDED_SSL", $_SERVER) && 'on' === $_SERVER["HTTP_X_FORWARDED_SSL"]) {
        return true;
    }
    if (array_key_exists("HTTP_X_FORWARDED_PROTO", $_SERVER) && 'https' === $_SERVER["HTTP_X_FORWARDED_PROTO"]) {
        return true;
    }
    return false;
}
4
ling

Ich finde diese Parameter ebenfalls akzeptabel und haben beim Wechsel von Webservern wahrscheinlich keine Fehlalarme.

  1. $ _SERVER ['HTTPS_KEYSIZE']
  2. $ _SERVER ['HTTPS_SECRETKEYSIZE']
  3. $ _SERVER ['HTTPS_SERVER_ISSUER']
  4. $ _SERVER ['HTTPS_SERVER_SUBJECT']

    if($_SERVER['HTTPS_KEYSIZE'] != NULL){/*do foobar*/}
    
3
Werezywolf

Die einzige zuverlässige Methode ist die von Igor M. beschriebene.

$pv_URIprotocol = isset($_SERVER["HTTPS"]) ? (($_SERVER["HTTPS"]==="on" || $_SERVER["HTTPS"]===1 || $_SERVER["SERVER_PORT"]===$pv_sslport) ? "https://" : "http://") :  (($_SERVER["SERVER_PORT"]===$pv_sslport) ? "https://" : "http://");

Erwägen Sie Folgendes: Sie verwenden nginx mit fastcgi. Standardmäßig (debian, ubuntu) enthalten die Befehle fastgi_params die Direktive:

fastcgi_param HTTPS $ https;

wenn Sie KEIN SSL verwenden, wird es als leerer Wert übersetzt, nicht als "aus" und nicht als 0 Sie sind zum Scheitern verurteilt.

http://unpec.blogspot.cz/2013/01/nette-nginx-php-fpm-redirect.html

3
Galvani

Ich denke nicht, dass das Hinzufügen eines Ports eine gute Idee ist - vor allem wenn Sie viele Server mit unterschiedlichen Builds haben. Das fügt nur noch eine weitere Sache hinzu, an die man sich erinnern muss. Wenn ich mir Docs anschaue, finde ich, dass die letzte Zeile der Kaiser ziemlich gut ist, so dass:

if(!empty($_SERVER["HTTPS"]))
  if($_SERVER["HTTPS"]!=="off")
    return 1; //https
  else
    return 0; //http
else
  return 0; //http

scheint perfekt zu sein.

3
sp3c1

Sie könnten $_SERVER['SERVER_PORT'] überprüfen, da SSL normalerweise an Port 443 ausgeführt wird. Dies ist jedoch nicht narrensicher.

2
pix0r

Was denkst du über dies?

if (isset($_SERVER['HTTPS']) && !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off')
    $scheme = 'https';
else
    $scheme = 'http';
2
toni rmc

Auf meinem Server (Ubuntu 14.10, Apache 2.4, PHP 5.5) wird die Variable $_SERVER['HTTPS'] nicht festgelegt, wenn das PHP-Skript über https geladen wird. Ich weiß nicht was falsch ist. Die folgenden Zeilen in .htaccess-Datei beheben dieses Problem:

RewriteEngine on

RewriteCond %{HTTPS} =on [NC] 
RewriteRule .* - [E=HTTPS:on,NE]
2
Karry

Kürzeste Art, wie ich benutze:

$secure_connection = !empty($_SERVER['HTTPS']);

Wenn https verwendet wird, ist $ secure_connection wahr.

2
Markus Zeller

nur für interesse, Chrom-Kanarienfisch im Moment sendet 

HTTPS : 1

auf dem Server, und je nachdem, wie der Server konfiguriert ist, erhalten Sie Folgendes:

HTTPS : 1, on

Das hat unsere Bewerbung gebrochen, weil wir getestet haben, was nicht der Fall ist. Im Moment scheint dies nur Chrom-Kanarienvogel zu tun, aber es ist erwähnenswert, dass Dinge aus Kanarienvogel in der Regel kurz danach in "normalem" Chrom landen.

1
John Smith

Hier ist eine wiederverwendbare Funktion, die ich seit einiger Zeit verwende. HTH.

Hinweis: Der Wert von HTTPS_PORT (der in meinem Code eine benutzerdefinierte Konstante ist) kann je nach Umgebung variieren, z. B. 443 oder 81.

/**
 * Determine if this is a secure HTTPS connection
 * 
 * @return  bool    True if it is a secure HTTPS connection, otherwise false.
 */
function isSSL()
{
    if (isset($_SERVER['HTTPS'])) {
        if ($_SERVER['HTTPS'] == 1) {
            return true;
        } elseif ($_SERVER['HTTPS'] == 'on') {
            return true;
        }
    } elseif ($_SERVER['SERVER_PORT'] == HTTPS_PORT) {
        return true;
    }

    return false;
}
1
crmpicco
$secure_connection = ((!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off') || (!empty($_SERVER['HTTP_HTTPS']) && $_SERVER['HTTP_HTTPS'] != 'off') || $_SERVER['REQUEST_SCHEME'] == 'https' || $_SERVER['SERVER_PORT'] == 443) ? true : false;

Code überprüft alles Mögliche und funktioniert auch auf IIS Webserver. Chrome seit v44 setzt den Header HTTP: 1 nicht. Daher ist die Überprüfung von HTTP_HTTPS in Ordnung. Wenn dieser Code nicht mit https übereinstimmt, ist Ihr Webserver oder Proxyserver schlecht konfiguriert. Apache selbst setzt das HTTPS-Flag richtig, aber es kann Probleme geben, wenn Sie einen Proxy (z. B. Nginx) verwenden. Sie müssen einige Header in nginx https virtual Host setzen

proxy_set_header   X-HTTPS 1;

und verwenden Sie ein Apache-Modul, um das HTTPS-Flag richtig zu setzen, indem Sie vom Proxy nach X-HTTPS suchen. Suche nach mod_fakessl, mod_rpaf usw.

1
mikep

Wenn Sie nginx als Loadbalancing-System verwenden, überprüfen Sie $ _SERVER ['HTTP_HTTPS'] == 1, dass andere Überprüfungen für SSL fehlschlagen.

1
basis

Ich habe Gelegenheit, einen Schritt weiter zu gehen und festzustellen, ob die Site, mit der ich mich verbinde, SSL-fähig ist (ein Projekt fragt den Benutzer nach der URL und wir müssen überprüfen, ob er unser API-Paket auf einer http- oder https-Site installiert hat).

Hier ist die Funktion, die ich verwende - im Allgemeinen rufen Sie einfach die URL über cURL auf, um zu sehen, ob https funktioniert!

function hasSSL($url) 
{
    // take the URL down to the domain name
    $domain = parse_url($url, PHP_URL_Host);
    $ch = curl_init('https://' . $domain);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'HEAD'); //its a  HEAD
    curl_setopt($ch, CURLOPT_NOBODY, true);          // no body
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);  // in case of redirects
    curl_setopt($ch, CURLOPT_VERBOSE, 0); //turn on if debugging
    curl_setopt($ch, CURLOPT_HEADER, 1);     //head only wanted
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);    // we dont want to wait forever
    curl_exec($ch);
    $header = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    if ($header === 200) {
        return true;
    }
    return false;
}

Dies ist die zuverlässigste Methode, die ich gefunden habe, um nicht nur herauszufinden, WENN Sie https verwenden (wie die Frage stellt), sondern ob Sie https verwenden könnten (oder auch nur SOLLTEN). 

HINWEIS: Es ist möglich (wenn auch nicht sehr wahrscheinlich ...), dass eine Website unterschiedliche http- und https-Seiten haben kann (wenn Sie also aufgefordert werden, http zu verwenden, müssen Sie möglicherweise nicht ändern.) Die große Mehrheit der Websites sind die gleichen und sollten Sie wahrscheinlich selbst umleiten, aber diese zusätzliche Überprüfung hat ihre Verwendung (sicherlich wie gesagt, in dem Projekt, in das der Benutzer seine Site-Informationen eingibt und Sie von der Serverseite sicherstellen möchten)

0
CFP Support

Ich habe den Hauptvorschlag hier verwendet und mich über die "PHP Notice" in den Logs geärgert, als HTTPS nicht gesetzt war. Sie können dies vermeiden, indem Sie den Operator Null-Koaleszenz "??" verwenden:

if( ($_SERVER['HTTPS'] ?? 'off') == 'off' ) {
    // redirect
}

(Hinweis: nicht verfügbar vor PHP v7)

0
garafajon

So finde ich das lösen

$https = !empty($_SERVER['HTTPS']) && strcasecmp($_SERVER['HTTPS'], 'on') === 0 ||
        !empty($_SERVER['HTTP_X_FORWARDED_PROTO']) &&
            strcasecmp($_SERVER['HTTP_X_FORWARDED_PROTO'], 'https') === 0;

return ($https) ? 'https://' : 'http://';
0

Ich würde einen globalen Filter hinzufügen, um sicherzustellen, dass alles, was ich überprüfe, korrekt ist.

function isSSL() {

    $https = filter_input(INPUT_SERVER, 'HTTPS');
    $port = filter_input(INPUT_SERVER, 'SERVER_PORT');
    if ($https) {

        if ($https == 1) {
            return true;
        } elseif ($https == 'on') {
            return true;
        }
    } elseif ($port == '443') {
        return true;
    }

    return false;
}
0
Rodrigo Manara

Wenn Sie den Lastenausgleich von Incapsula verwenden, müssen Sie eine IRule verwenden, um einen benutzerdefinierten Header für Ihren Server zu generieren. Ich habe einen HTTP_X_FORWARDED_PROTO-Header erstellt, der entweder "http" entspricht, wenn der Port auf 80 festgelegt ist, und "https", wenn er 443 entspricht.

0
Nadav