1 votes

Règles de réécriture HTTPS / HTTP mod_rewrite, interaction étrange avec la réécriture ultérieure du CMS index.php

Avec les réécritures ci-dessous dans htaccess, comme prévu cette requête HTTPS est pas réécrit :

https://example.com/system/anything

n'est pas réécrit pour

http://example.com/system/anything

Mais, de manière inattendue, cette requête HTTPS est réécrite :

https://example.com/preview/anything

est réécrit pour

http://example.com/index.php/preview/anything

Pourquoi ?

Quelques autres faits / observations :

/system/ est un chemin d'accès réel sur le serveur. Mais /preview/ n'est pas un chemin réel - c'est un segment d'URL qui a un sens dans le CMS, par exemple, /index.php/preview/anything est la façon dont le CMS reçoit la demande pour le /preview/anything URL.

D'autres URL non liées au système se réécrivent correctement (de HTTPS à HTTP), et sont correctement transmises à index.php. Par exemple,

https://example.com/real

est réécrit pour

http://example.com/real

Voici le bloc complet de règles :

 <IfModule mod_rewrite.c>
 RewriteEngine On
 RewriteBase /

 # Force HTTPS for System URLs
 RewriteCond %{REQUEST_URI} ^/system(.*)$ [NC]
 RewriteCond %{HTTPS} !=on
 RewriteRule ^(.*)$ "https://example.com/$1" [R=301,L]

 # Force HTTP for Other URLs, but not: system or preview
 RewriteCond %{REQUEST_URI} !^/(system|preview)/(.*)$ [NC]
 RewriteCond %{HTTPS} =on
 RewriteRule ^(.*)$ "http://example.com/$1" [R=302,L]

 RewriteCond %{REQUEST_FILENAME} !-f
 RewriteCond %{REQUEST_FILENAME} !-d
 RewriteRule ^(.*)$ /index.php/$1 [L]
 </IfModule>

Un aperçu de la raison pour laquelle /preview/ reçoit le traitement bizarre ?


Ajouté : Notez que /preview/anything obtient un 302 rediriger vers /index.php/preview/anything -- et c'est en grande partie ce qui semble si bizarre / inattendu. Il ne devrait pas y avoir de redirection dans la règle finale, mais seulement une réécriture.

1voto

Sergey Vlasov Points 6068

Ces règles de réécriture sont-elles dans un .htaccess fichier ? Dans ce cas le site [L] le drapeau ne fait pas ce que vous pensez qu'il fait  - il arrête le traitement du jeu de règles en cours, mais la requête est ensuite traitée à nouveau par Apache, en utilisant la méthode .htaccess appropriés pour l'URI réécrit, donc vos règles peuvent être exécutées à nouveau. Ceci ne se produit pas pour les règles qui se trouvent dans le fichier de configuration d'Apache (et non dans un fichier <Directory> ) - dans ce cas, la [L] est traité comme prévu.

Pour votre exemple, https://example.com/preview/anything est réécrit en interne en https://example.com/index.php/preview/anything par la troisième règle ; cependant, afin de traiter cette demande, Apache doit lire la .htaccess et cette fois-ci, l'URI correspond à votre deuxième règle, qui renvoie un fichier 302 réorienter.

Apache 2.4.x soutient le [END] qui arrête ces boucles de réécriture, contrairement à l'indicateur [L] ; les solutions pour les versions antérieures d'Apache sont plus complexes.

Si vous voulez vous assurer qu'Apache n'effectue qu'un seul passage sur vos règles de réécriture, vous pouvez ajouter la règle suivante avant toutes les autres :

RewriteCond %{ENV:REDIRECT_STATUS} !=""
RewriteRule ^ - [L]

Au premier passage REDIRECT_STATUS sera vide ; au deuxième passage, il aura une valeur non vide (habituellement 200 ), et la règle correspondra et arrêtera réellement les réécritures ultérieures.

Si une telle règle n'est pas appropriée (par exemple, dans certains cas, vous devez traiter les URI réécrits au deuxième passage), vous pouvez définir une variable d'environnement dans les règles qui doivent être vraiment finales :

RewriteRule ^(.*)$ /index.php/$1 [L,E=FINISH:1]

et ajoutez la règle suivante avant toutes les autres :

RewriteCond %{ENV:REDIRECT_FINISH} !=""
RewriteRule ^ - [L]

Notez qu'au cours de la seconde passe, Apache ajoute en début de ligne REDIRECT_ à des noms de variables d'environnement qui ont été définis lors de la première passe, vous devez donc configurer FINISH mais le test REDIRECT_FINISH .

Vous pouvez également essayer de modifier vos conditions de correspondance de sorte que, lors du deuxième passage, les URI modifiés lors du premier passage ne soient pas mis en correspondance (par exemple, insérer (index\.php/)? dans le regexp de la deuxième règle).

0voto

cnst Points 12508

Cela ressemble à la dernière règle qui introduit un absolu http lorsqu'elle est effectuée, peut-être en raison d'un bogue ou d'une fonctionnalité d'Apache ou de mod_rewrite.

Et si vous le décomposiez en deux règles avec une condition supplémentaire ?

Essayez ça :

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{HTTPS} =off
RewriteRule ^(.*)$ http://example.com/index.php/$1 [L]

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{HTTPS} =on
RewriteRule ^(.*)$ https://example.com/index.php/$1 [L]

0voto

Archie1986 Points 695

Est-ce que le http (au lieu de https ) qui vous dérange ? Si c'est le cas, vous devriez consulter le RewriteBase directive.

De la Documentation sur le mod_rewrite :

El RewriteBase spécifie le préfixe d'URL à utiliser pour l'accès par répertoire (htaccess). RewriteRule qui substituent un chemin relatif.

Cette directive est nécessaire lorsque vous utilisez un chemin d'accès relatif dans une substitution dans un contexte par répertoire (htaccess) (...)

0voto

reconbot Points 143

Je ne pense pas que vous ayez besoin des '(.*)$' à la fin des instructions RewriteCond, car vous n'utilisez les données capturées nulle part. Vous pourriez simplifier ces 2 déclarations comme suit :

RewriteCond %{REQUEST_URI} ^/system [NC]

et RewriteCond %{REQUEST_URI} !^/(system|preview)/ [NC]

Je vous recommande également d'activer RewriteLog et de définir RewriteLogLevel pour voir exactement ce qu'Apache fait par requête. Avec apache 2.2 ou moins, ce serait :

RewriteLog /var/log/apache2/rewrite.log
RewriteLogLevel 7

Vous devriez voir étape par étape ce qui correspond et ce que Apache a fait.

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X