Erzwingen Sie SSL / https mit .htaccess und mod_rewrite

234

Wie kann ich mithilfe der in PHP spezifischen Seite .htaccess und mod_rewrite SSL / https erzwingen?

Sanjay Shah
quelle

Antworten:

438

Für Apache können Sie mod_sslSSL erzwingen mit SSLRequireSSL Directive:

Diese Anweisung verbietet den Zugriff, es sei denn, HTTP über SSL (dh HTTPS) ist für die aktuelle Verbindung aktiviert. Dies ist sehr praktisch im SSL-fähigen virtuellen Host oder in den Verzeichnissen, um sich gegen Konfigurationsfehler zu schützen, die Dinge offenlegen, die geschützt werden sollten. Wenn diese Anweisung vorhanden ist, werden alle Anforderungen abgelehnt, die kein SSL verwenden.

Dies führt jedoch keine Umleitung zu https durch. Versuchen Sie zum Umleiten Folgendes mit mod_rewritein Ihrer .htaccess-Datei

RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

oder einer der verschiedenen Ansätze unter

Sie können dies auch in PHP lösen, falls Ihr Provider .htaccess deaktiviert hat (was unwahrscheinlich ist, da Sie danach gefragt haben, aber trotzdem).

if (!isset($_SERVER['HTTPS']) || $_SERVER['HTTPS'] !== 'on') {
    if(!headers_sent()) {
        header("Status: 301 Moved Permanently");
        header(sprintf(
            'Location: https://%s%s',
            $_SERVER['HTTP_HOST'],
            $_SERVER['REQUEST_URI']
        ));
        exit();
    }
}
Gordon
quelle
1
Dies ist in unserer Situation großartig, da wir derzeit eine Mischung aus http- und https-Verkehr haben. Für unseren Admin-Bereich haben wir gerade das .htaccess-Skript eingeblendet, während der Rest der Site http beibehalten wurde.
Michael J. Calkins
1
Wenn ich die mod_rewrite-Methode verwende, werde ich an https gesendet, aber mit dem Fehler "Die Seite wird nicht richtig umgeleitet".
Czechnology
11
Follow-up: Wenn Sie ähnliche Probleme haben, überprüfen Sie Ihre Server- und HTTP-Variablen. Wenn an Ihrem Server - Proxies, können Sie verwenden %{HTTP:X-Forwarded-Proto}oder %{HTTP:X-Real-Port}Variablen zu prüfen , ob SSL aktiviert ist.
Czechnology
8
Wenn Sie erleben Umleitung Schleifen hinter Proxies (läuft auf Servern CloudFlare , Openshift ), sehen Sie diese Antwort für eine Lösung , die funktioniert für diesen Fall zu.
Raphinesse
4
@GTodorov - Das Entfernen des Leerzeichens hat die Umschreibung für mich gebrochen. Nach meinem (begrenzten) Wissen über Umschreibungen ist die Syntax RewriteRule <input-pattern> <output-url>. Daher muss der Speicherplatz vorhanden sein, und die Single ^sagt nur "Alle Eingabe-URLs abgleichen".
Sphinxxx
54

Ich habe eine mod_rewriteLösung gefunden, die sowohl für Proxyserver als auch für nicht Proxyserver gut funktioniert.

Wenn Sie CloudFlare, AWS Elastic Load Balancing, Heroku, OpenShift oder eine andere Cloud / PaaS-Lösung verwenden und Umleitungsschleifen mit normalen HTTPS-Umleitungen auftreten, versuchen Sie stattdessen das folgende Snippet.

RewriteEngine On

# If we receive a forwarded http request from a proxy...
RewriteCond %{HTTP:X-Forwarded-Proto} =http [OR]

# ...or just a plain old http request directly from the client
RewriteCond %{HTTP:X-Forwarded-Proto} =""
RewriteCond %{HTTPS} !=on

# Redirect to https version
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
raphinesse
quelle
Das ist genial, danke! Aber vielleicht ist es erforderlich, eine Nachbedingung hinzuzufügen? RewriteCond% {REQUEST_METHOD}! ^ POST $
Aleksej
@Aleksej True, dies unterbricht unverschlüsselte POST-Anforderungen. Aber ich denke das ist eine gute Sache. Auf diese Weise werden die Leute bemerken, dass sie etwas falsch machen. Ich denke, das Beste wäre, sie auf eine Seite umzuleiten, die sie darüber informiert, wie Sie Ihren Dienst richtig nutzen können.
Raphinesse
@raphinesse Kennen Sie die Antwort auf diese Frage: stackoverflow.com/questions/51951082/...
RRN
36

PHP-Lösung

In Anlehnung an Gordons sehr umfassende Antwort stelle ich fest, dass in Ihrer Frage erwähnt wird, dass das Erzwingen von HTTPS / SSL-Verbindungen seitenspezifisch ist.

function forceHTTPS(){
  $httpsURL = 'https://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
  if( count( $_POST )>0 )
    die( 'Page should be accessed with HTTPS, but a POST Submission has been sent here. Adjust the form to point to '.$httpsURL );
  if( !isset( $_SERVER['HTTPS'] ) || $_SERVER['HTTPS']!=='on' ){
    if( !headers_sent() ){
      header( "Status: 301 Moved Permanently" );
      header( "Location: $httpsURL" );
      exit();
    }else{
      die( '<script type="javascript">document.location.href="'.$httpsURL.'";</script>' );
    }
  }
}

Ganz oben auf diesen Seiten, die Sie über PHP verbinden möchten, können Sie require()eine zentralisierte Datei mit dieser (und allen anderen) benutzerdefinierten Funktionen erstellen und die Funktion dann einfach ausführen forceHTTPS().

HTACCESS / mod_rewrite-Lösung

Ich habe diese Art von Lösung nicht persönlich implementiert (ich habe der Einfachheit halber eher die PHP-Lösung wie die oben genannte verwendet), aber das Folgende kann zumindest ein guter Anfang sein.

RewriteEngine on

# Check for POST Submission
RewriteCond %{REQUEST_METHOD} !^POST$

# Forcing HTTPS
RewriteCond %{HTTPS} !=on [OR]
RewriteCond %{SERVER_PORT} 80
# Pages to Apply
RewriteCond %{REQUEST_URI} ^something_secure [OR]
RewriteCond %{REQUEST_URI} ^something_else_secure
RewriteRule .* https://%{SERVER_NAME}%{REQUEST_URI} [R=301,L]

# Forcing HTTP
RewriteCond %{HTTPS} =on [OR]
RewriteCond %{SERVER_PORT} 443
# Pages to Apply
RewriteCond %{REQUEST_URI} ^something_public [OR]
RewriteCond %{REQUEST_URI} ^something_else_public
RewriteRule .* http://%{SERVER_NAME}%{REQUEST_URI} [R=301,L]
Luke Stevenson
quelle
aus Neugier, warum die RewriteCond %{REQUEST_METHOD} !^POST$?
Depoulo
12
Weil POST-Parameter bei einer Umleitung nicht beibehalten werden. Sie können diese Zeile weglassen, wenn Sie sicherstellen möchten, dass alle POST-Übermittlungen sicher sind (ungesicherte POST-Übermittlungen werden ignoriert).
Luke Stevenson
@Lucanos - Wie schreibe ich eine RewriteCond, die beim POST keine Umleitung zu http oder https erzwingt? Mein .htaccess erzwingt HTTPS auf bestimmten Seiten und dann HTTP für den Rest. Auf den HTTPS-Seiten gibt es jedoch Formulare, die an mein Webstamm gesendet werden. Das Formular gibt die Aktions-URL als HTTPS an. Da das Webstammverzeichnis jedoch nicht zu den Seiten gehört, auf denen HTTPS erzwungen werden soll, erzwingt mein .htaccess eine Umleitung. Dies bedeutet, dass die POST-Variablen verloren gehen. Wie verhindere ich Weiterleitungen auf POST?
StackOverflowNewbie
1
@StackOverflowNewbie: Die Zeile RewriteCond %{REQUEST_METHOD} !^POST$sollte verhindern, dass POST- Übermittlungen von diesen Umleitungen betroffen sind.
Luke Stevenson
Ich mag diese PHP-Version. Es ist viel besser, da es einen POST berücksichtigt und besser verarbeitet wird, wenn bereits Header gesendet wurden.
TheStoryCoder
10

Mod-rewrite-basierte Lösung:

Wenn Sie den folgenden Code in htaccess verwenden, werden alle http-Anforderungen automatisch an https weitergeleitet.

RewriteEngine on

RewriteCond %{HTTPS}::%{HTTP_HOST} ^off::(?:www\.)?(.+)$
RewriteRule ^ https://www.%1%{REQUEST_URI} [NE,L,R]

Dadurch werden Ihre Nicht-www- und www- http-Anforderungen an die www- Version von https umgeleitet .

Eine andere Lösung (Apache 2.4 *)

RewriteEngine on

RewriteCond %{REQUEST_SCHEME}::%{HTTP_HOST} ^http::(?:www\.)?(.+)$
RewriteRule ^ https://www.%1%{REQUEST_URI} [NE,L,R]

Dies funktioniert nicht bei niedrigeren Versionen von Apache, da die Variable% {REQUEST_SCHEME} seit 2.4 zu mod-rewrite hinzugefügt wurde.

starkeen
quelle
9

Ich möchte nur darauf hinweisen, dass Apache die schlechtesten Vererbungsregeln hat, wenn mehrere .htaccess-Dateien über Verzeichnis-Tiefen hinweg verwendet werden. Zwei wichtige Fallstricke:

  • Standardmäßig werden nur die Regeln ausgeführt, die in der tiefsten .htaccess-Datei enthalten sind. Sie müssen die RewriteOptions InheritDownBeforeDirektive (oder eine ähnliche) angeben , um dies zu ändern. (siehe Frage)
  • Das Muster wird auf den Dateipfad relativ zum Unterverzeichnis angewendet und nicht auf das obere Verzeichnis, das die .htaccess-Datei mit der angegebenen Regel enthält. (siehe Diskussion)

Das heißt , die vorgeschlagene globale Lösung auf dem Apache - Wiki hat nicht funktioniert , wenn Sie irgendwelche andere .htaccess - Dateien in Unterverzeichnissen verwendet werden . Ich habe eine modifizierte Version geschrieben, die Folgendes tut:

RewriteEngine On
# This will enable the Rewrite capabilities

RewriteOptions InheritDownBefore
# This prevents the rule from being overrided by .htaccess files in subdirectories.

RewriteCond %{HTTPS} !=on
# This checks to make sure the connection is not already HTTPS

RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [QSA,R,L]
# This rule will redirect users from their original location, to the same location but using HTTPS.
# i.e.  http://www.example.com/foo/ to https://www.example.com/foo/
lpd
quelle
0

Einfach und leicht, fügen Sie einfach Folgendes hinzu

RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
Saurabh Mistry
quelle
Dies ist so ziemlich das, was die Leute im Internet Ihnen sagen, um https zu erzwingen. Jedes Mal, wenn ich das tue, wird meine gesamte Website VERBOTEN oder Sie haben keine Berechtigung zum Anzeigen. so etwas ... Was mache ich falsch? Ich möchte nur wissen, ob Sie eine Idee haben, bevor ich eine Frage dazu stelle.
Do
Ich hatte ein ähnliches Problem und musste die Regeln auf die Datei https.conf anwenden. Siehe meine Antwort unten.
Risteard
-1

Dieser Code funktioniert für mich

RewriteEngine On
RewriteBase /
RewriteCond %{HTTP:X-HTTPS} !1
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]
Alexufo
quelle
-1

Einfache Sache :

RewriteEngine on
RewriteCond %{HTTP_HOST} ^(www\.example\.com)(:80)? [NC]
RewriteRule ^(.*) https://example.com/$1 [R=301,L]
order deny,allow

Ersetzen Sie Ihre URL durch example.com

Sepehr Norouzi
quelle
NEIN! Die Site-URL muss dynamisch sein.
Amir Savand
-1

Sie können SSL nur mit Apache .htaccess erzwingen

SSLOptions +StrictRequire
SSLRequireSSL

Für die Weiterleitung ist die obige Antwort korrekt

webdesignwien
quelle
-1

Versuchen Sie diesen Code, es wird für alle Versionen von URLs wie funktionieren

  • website.com
  • www.website.com
  • http://website.com
  • http://www.website.com

    RewriteCond %{HTTPS} off
    RewriteCond %{HTTPS_HOST} !^www.website.com$ [NC]
    RewriteRule ^(.*)$ https://www.website.com/$1 [L,R=301]
Kashif Latif
quelle