Forcer SSL / https en utilisant .htaccess et mod_rewrite

234

Comment puis-je forcer à SSL / https en utilisant la page .htaccess et mod_rewrite spécifique à PHP.

Sanjay Shah
la source

Réponses:

438

Pour Apache, vous pouvez utiliser mod_sslpour forcer SSL avec SSLRequireSSL Directive:

Cette directive interdit l'accès à moins que HTTP sur SSL (c'est-à-dire HTTPS) soit activé pour la connexion actuelle. C'est très pratique à l'intérieur de l'hôte virtuel ou des répertoires compatibles SSL pour se défendre contre les erreurs de configuration qui exposent des éléments qui doivent être protégés. Lorsque cette directive est présente, toutes les demandes refusées n'utilisant pas SSL.

Cependant, cela ne fera pas de redirection vers https. Pour rediriger, essayez ce qui suit avec mod_rewritedans votre fichier .htaccess

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

ou l'une des différentes approches données à

Vous pouvez également résoudre ce problème à partir de PHP au cas où votre fournisseur aurait désactivé .htaccess (ce qui est peu probable depuis que vous l'avez demandé, mais de toute façon)

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
la source
1
C'est très bien dans notre situation car nous avons actuellement un mélange de trafic http et https. Pour notre zone d'administration, nous avons simplement ajouté le script .htaccess tout en conservant le reste du site http.
Michael J.Calkins du
1
Lorsque j'utilise la méthode mod_rewrite, je suis envoyé vers https mais avec une erreur "La page ne redirige pas correctement".
Czechnology,
11
Suivi: si vous rencontrez des problèmes similaires, vérifiez votre serveur et les variables HTTP. Si votre serveur utilise des proxys, vous pouvez utiliser des variables %{HTTP:X-Forwarded-Proto}ou %{HTTP:X-Real-Port}pour vérifier si SSL est activé.
Czechnology
8
Si vous rencontrez des boucles de redirection sur des serveurs exécutant des proxys ( CloudFlare , Openshift ), consultez cette réponse pour une solution qui fonctionne également pour ce cas.
raphinesse
4
@GTodorov - La suppression de l'espace a brisé la réécriture pour moi. D'après ma connaissance (limitée) des réécritures, la syntaxe est RewriteRule <input-pattern> <output-url>. Ainsi, l'espace doit être là, et le single ^dit simplement "correspondre à toutes les URL d'entrée".
Sphinxxx
54

J'ai trouvé une mod_rewritesolution qui fonctionne bien pour les serveurs proxy et non proxy.

Si vous utilisez CloudFlare, AWS Elastic Load Balancing, Heroku, OpenShift ou toute autre solution Cloud / PaaS et que vous rencontrez des boucles de redirection avec des redirections HTTPS normales, essayez plutôt l'extrait de code suivant.

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
la source
C'est génial thx! Mais peut-être qu'il est nécessaire d'ajouter une condition de publication? RewriteCond% {REQUEST_METHOD}! ^ POST $
Aleksej
@Aleksej Vrai, cela rompt les demandes POST non chiffrées. Mais je pense que c'est une bonne chose. De cette façon, les gens remarqueront qu'ils font quelque chose de mal. Je suppose que la meilleure chose serait de les rediriger vers une page qui les informe sur la façon d'utiliser correctement votre service.
raphinesse
@raphinesse Connaissez-vous la réponse à cette question: stackoverflow.com/questions/51951082/…
RRN
36

Solution PHP

En empruntant directement à la réponse très complète de Gordon, je note que votre question mentionne être spécifique à la page pour forcer les connexions HTTPS / SSL.

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>' );
    }
  }
}

Ensuite, aussi près du haut de ces pages que vous souhaitez forcer à se connecter via PHP, vous pouvez require()un fichier centralisé contenant cette (et toute autre) fonctions personnalisées, puis exécutez simplement la forceHTTPS()fonction.

Solution HTACCESS / mod_rewrite

Je n'ai pas implémenté ce type de solution personnellement (j'ai eu tendance à utiliser la solution PHP, comme celle ci-dessus, pour sa simplicité), mais ce qui suit peut être, au moins, un bon début.

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
la source
par curiosité, pourquoi le RewriteCond %{REQUEST_METHOD} !^POST$?
depoulo
12
Parce que les paramètres POST ne sont pas conservés sur une redirection. Vous pouvez omettre cette ligne si vous voulez vous assurer que toutes les soumissions POST sont sécurisées (toutes les soumissions POST non sécurisées seront ignorées).
Luke Stevenson
@Lucanos - Comment écrire un RewriteCond qui ne force pas une redirection vers http ou https lors du POST? Mon .htaccess force HTTPS sur certaines pages spécifiques, puis force HTTP sur les autres. Cependant, sur les pages HTTPS, il existe des formulaires qui se soumettent à ma racine Web. Le formulaire spécifie l'URL de l'action en HTTPS. Cependant, comme la racine Web ne fait pas partie de ces pages qui sont spécifiées pour forcer HTTPS, mon .htaccess force alors une redirection - ce qui signifie que les variables POST sont perdues. Comment empêcher les redirections sur POST?
StackOverflowNewbie
1
@StackOverflowNewbie: la ligne RewriteCond %{REQUEST_METHOD} !^POST$devrait empêcher les soumissions POST d'être affectées par ces redirections.
Luke Stevenson
J'aime cette version PHP. C'est beaucoup mieux car il considère un POST et se comporte mieux si des en-têtes ont déjà été envoyés.
TheStoryCoder
10

Solution basée sur la réécriture de modules:

L'utilisation du code suivant dans htaccess transfère automatiquement toutes les requêtes http à https.

RewriteEngine on

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

Cela redirigera vos demandes non www et www http vers www version de https.

Une autre solution (Apache 2.4 *)

RewriteEngine on

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

Cela ne fonctionne pas sur les versions inférieures d'apache car la variable% {REQUEST_SCHEME} a été ajoutée à mod-rewrite depuis 2.4.

starkeen
la source
9

Je voudrais juste souligner qu'Apache a les pires règles d'héritage lors de l'utilisation de plusieurs fichiers .htaccess à travers les profondeurs de répertoire. Deux pièges clés:

  • Seules les règles contenues dans le fichier .htaccess le plus profond seront exécutées par défaut. Vous devez spécifier la RewriteOptions InheritDownBeforedirective (ou similaire) pour changer cela. (voir question)
  • Le modèle est appliqué au chemin d'accès au fichier par rapport au sous-répertoire et non au répertoire supérieur contenant le fichier .htaccess avec la règle donnée. (voir discussion)

Cela signifie que la solution globale suggérée sur le wiki Apache ne fonctionne pas si vous utilisez d'autres fichiers .htaccess dans les sous-répertoires. J'ai écrit une version modifiée qui fait:

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
la source
0

Simple et facile, ajoutez simplement le suivant

RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
Saurabh Mistry
la source
C'est à peu près ce que les gens partout sur Internet vous disent de faire pour forcer https. Cependant, chaque fois que je fais cela, mon site Web entier devient INTERDIT ou vous n'avez aucune permission de le voir. quelque chose comme ça ... Qu'est-ce que je fais mal? Je veux juste savoir si vous avez une idée avant de poster une question à ce sujet.
2018 à 13h53
J'ai eu un problème similaire et j'ai dû appliquer les règles au fichier https.conf. Voir ma réponse ci-dessous.
Risteard
-1

Ce code fonctionne pour moi

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

Simple:

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

remplacez votre URL par example.com

Sepehr Norouzi
la source
NON! L'URL du site doit être dynamique.
Amir Savand
-1

pour forcer simplement SSL avec Apache .htaccess, vous pouvez utiliser

SSLOptions +StrictRequire
SSLRequireSSL

pour rediriger la réponse ci-dessus est correcte

webdesignwien
la source
-1

essayez ce code, il fonctionnera pour toutes les versions d'URL comme

  • 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
la source