Le fichier .htaccess quésaco ?

Le .htaccess est un fichier texte de configuration pour paramétrer un serveur web sous Apache afin d’appliquer certaines optimisations pour un site web plus rapide et une meilleure sécurité. Il peut se situer à la racine de l’espace web ou dans n’importe quel autre dossier. Les directives indiquées s’appliqueront au dossier et aux sous-dossiers dans lequel il se trouve. Il permet de réaliser des optimisations, des redirections ou de sécuriser l’accès à certains fichiers et répertoires. Il peut modifier le comportement par défaut du fichier httpd.conf et du php.ini selon les hébergeurs. Il est préférable d’utiliser directement les fichiers de configuration du serveur, mais dans certains cas, comme sur un hébergement web mutualisé, il n’est pas possible d’y accéder.

Ce fichier de configuration est exclusivement utilisé sur un serveur web Apache. Il n’est donc pas possible de l’intégrer sur un serveur Nginx ou Node.js par exemple cela ne fonctionnera pas. La documentation renseigne sur son utilisation et les différentes directives qu’on peut lui appliquer. Il faut faire attention à ne jamais le modifier directement sur un site web en production sans l’avoir préalablement bien testé. Une mauvaise configuration peut entraîner une 500 Internal Server Error rendant un site indisponible. Vérifier en local ou sur un serveur de préprod le bon fonctionnement du .htaccess avant de l’uploader dans le répertoire racine de son un site web.

Modifier la configuration d’un serveur web avec le fichier .htaccess

Les conteneurs de section

Les directives indiquées dans un fichier .htaccess peuvent s’appliquer selon des conditions. Ces conteneurs de sections de configuration sont de plusieurs types. Le ifDefine s’applique que sur les constantes utilisées lors du démarrage du serveur par la ligne de commande. Le ifModule, comme dans l’exemple ci-dessous, s’applique que si le module est disponible. Il existe aussi la condition ifVersion dépendant de la version du serveur.

<ifModule mod_headers.c>
  Header always set X-FRAME-OPTIONS "SAMEORIGIN"
  ...
</ifModule>

Les conteneurs de système de fichier quant à eux appliqueront les directives renseignées seulement dans le répertoire ou le fichier indiqué. On retrouve les conteneurs Directory ou Files par exemple qui permettent de cibler seulement le répertoire ou le fichier sur le serveur. Il existe d’autres conteneurs sur la documentation des sections.

<Directory "/var/www/inc">
  Options +Indexes
  ...
</Directory>

<Files .htaccess>
  order allow,deny
  deny from all
</Files>

Sécuriser les en-têtes des requêtes

La sécurisation des en-têtes permet en 3 lignes de sécuriser son site sur plusieurs failles de sécurité. La directive X-FRAME-OPTIONS va empêcher un site malveillant d’afficher un autre site dans une iframe, X-XSS-Protection permet de se prémunir des attaques XSS et X-Content-Type-Options sécurise contre le MIME sniffing.

<ifModule mod_headers.c>
  Header always set X-FRAME-OPTIONS "SAMEORIGIN"
  Header always set X-XSS-Protection "1; mode=block"
  Header always set X-Content-Type-Options "nosniff"
</ifModule>

Optimiser le cache du navigateur

Pour optimiser le cache des assets d’un site Internet pour les navigateurs, il est possible d’opérer sur l’en-tête des requêtes avec le Cache-Control et sur l’expiration avec la directive ExpiresByType. En dessous du délai indiqué via max-age et access plus, toute requête d’un navigateur va utiliser les assets au niveau du cache au lieu de les retélécharger du serveur. Cela va servir surtout pour les visiteurs qui naviguent sur plusieurs pages du site ou ceux qui reviennent après un certain délai.

<ifModule mod_headers.c>
  <filesmatch "\\.(ico|jpe?g|png|gif|swf|gz|ttf|woff|woff2)$">
    Header set Cache-Control "max-age=31536000, public"
  </filesmatch>
  <filesmatch "\\.(css|js)$">
    Header set Cache-Control "max-age=14400, private"
  </filesmatch>
  <filesmatch "\.(pl|php|cgi|spl|scgi|fcgi)$">
    Header unset Cache-Control
  </filesmatch>
</ifModule>

<ifModule mod_expires.c>
  ExpiresActive On
  ExpiresDefault "access plus 7200 seconds"
  ExpiresByType image/jpeg "access plus 31536000 seconds"
  ExpiresByType image/png "access plus 31536000 seconds"
  ExpiresByType image/gif "access plus 31536000 seconds"
  ExpiresByType image/ico "access plus 31536000 seconds"
  ExpiresByType image/icon "access plus 31536000 seconds"
  ExpiresByType image/x-icon "access plus 31536000 seconds"
  ExpiresByType image/svg+xml "access plus 31536000 seconds"
  ExpiresByType image/vnd.microsoft.icon "access plus 31536000 seconds"
  ExpiresByType text/css "access plus 14400 seconds"
  ExpiresByType text/javascript "access plus 14400 seconds"
  ExpiresByType text/html "access plus 7200 seconds"
  ExpiresByType text/xml "access plus 31536000 seconds"
  ExpiresByType application/xhtml+xml "access plus 14400 seconds"
  ExpiresByType application/javascript "access plus 14400 seconds"
  ExpiresByType application/x-javascript "access plus 31536000 seconds"
  ExpiresByType application/x-shockwave-flash "access plus 31536000 seconds"
  ExpiresByType video/x-flv "access plus 31536000 seconds"
</ifModule>

Compresser les requêtes

Il est possible de compresser certaines données renvoyées par le serveur avec les formats gzip et zlib. Pour cela il faut que les modules mod_gzip et mod_deflate soient installés sur le serveur web. Les éléments à compresser concernent surtout la sortie HTML ainsi que les images et les assets CSS et JavaScript pour qu’ils soient un peu plus légers à télécharger.

<ifModule mod_gzip.c>
  mod_gzip_on Yes
  mod_gzip_dechunk Yes
  mod_gzip_item_include file \.(html?|txt|css|js|php|pl)$
  mod_gzip_item_include handler ^cgi-script$
  mod_gzip_item_include mime ^text/.*
  mod_gzip_item_include mime ^application/x-javascript.*
  mod_gzip_item_exclude mime ^image/.*
  mod_gzip_item_exclude rspheader ^Content-Encoding:.*gzip.*
</ifModule>

<IfModule mod_deflate.c>
  SetOutputFilter DEFLATE
  AddOutputFilterByType DEFLATE text/html text/xml application/xhtml+xml text/plain text/css text/javascript application/javascript
  SetEnvIfNoCase Request_URI \.(zip|rar|pdf|mp4|wmv)$ no-gzip Vary Accept-Encoding
</IfModule>

Autres fonctionnalités du .htaccess

Il existe d’autres fonctionnalités que l’on peut faire à partir d’un fichier .htaccess pour modifier la configuration par défaut d’Apache. Par exemple, on peut réaliser des redirections avec le module mod_rewrite ou bien personnaliser les messages d’erreur avec la directive ErrorDocument. Il est possible de modifier le fichier d’index par défaut d’un répertoire avec la directive DirectoryIndex. Enfin on peut bloquer l’indexation d’un répertoire avec Options -Indexes afin d’empêcher à un visiteur de voir tous les fichiers qui s’y trouvent. Ci-dessous un récapitulatif d’un fichier .htaccess à mettre dans le répertoire public de son serveur en production pour une bonne configuration au niveau sécurité et optimisation.

Options -Indexes

<ifModule mod_headers.c>
  Header always set X-FRAME-OPTIONS "SAMEORIGIN"
  Header always set X-XSS-Protection "1; mode=block"
  Header always set X-Content-Type-Options "nosniff"
  <filesmatch "\\.(ico|jpe?g|png|gif|swf|gz|ttf|css|woff|woff2)$">
    Header set Cache-Control "max-age=31536000, public"
  </filesmatch>
  <filesmatch "\\.(js)$">
    Header set Cache-Control "max-age=2592000, private"
  </filesmatch>
  <filesmatch "\.(pl|php|cgi|spl|scgi|fcgi)$">
    Header unset Cache-Control
  </filesmatch>
</ifModule>

<ifModule mod_expires.c>
  ExpiresActive On
  ExpiresDefault "access plus 7200 seconds"
  ExpiresByType image/jpeg "access plus 31536000 seconds"
  ExpiresByType image/png "access plus 31536000 seconds"
  ExpiresByType image/gif "access plus 31536000 seconds"
  ExpiresByType image/ico "access plus 31536000 seconds"
  ExpiresByType image/icon "access plus 31536000 seconds"
  ExpiresByType image/x-icon "access plus 31536000 seconds"
  ExpiresByType image/svg+xml "access plus 31536000 seconds"
  ExpiresByType image/vnd.microsoft.icon "access plus 31536000 seconds"
  ExpiresByType text/css "access plus 14400 seconds"
  ExpiresByType text/javascript "access plus 14400 seconds"
  ExpiresByType text/html "access plus 7200 seconds"
  ExpiresByType text/xml "access plus 31536000 seconds"
  ExpiresByType application/xhtml+xml "access plus 14400 seconds"
  ExpiresByType application/javascript "access plus 14400 seconds"
  ExpiresByType application/x-javascript "access plus 31536000 seconds"
  ExpiresByType application/x-shockwave-flash "access plus 31536000 seconds"
  ExpiresByType video/x-flv "access plus 31536000 seconds"
</ifModule>

<ifModule mod_gzip.c>
  mod_gzip_on Yes
  mod_gzip_dechunk Yes
  mod_gzip_item_include file \.(html?|txt|css|js|php|pl)$
  mod_gzip_item_include handler ^cgi-script$
  mod_gzip_item_include mime ^text/.*
  mod_gzip_item_include mime ^application/x-javascript.*
  mod_gzip_item_exclude mime ^image/.*
  mod_gzip_item_exclude rspheader ^Content-Encoding:.*gzip.*
</ifModule>

<IfModule mod_deflate.c>
  SetOutputFilter DEFLATE
  AddOutputFilterByType DEFLATE text/html text/xml application/xhtml+xml text/plain text/css text/javascript application/javascript
  SetEnvIfNoCase Request_URI \.(zip|rar|pdf|mp4|wmv)$ no-gzip Vary Accept-Encoding
</IfModule>

<Files .htaccess>
  order allow,deny
  deny from all
</Files>