Comprendre le fichier .htaccess

Le fichier .htaccess est un fichier de configuration Apache qui s'applique au répertoire où il se trouve et à tous ses sous-répertoires. Sur WordPress, il se trouve à la racine du site et contient par défaut les règles de réécriture d'URL de WordPress.

Sauvegardez toujours votre .htaccess actuel avant toute modification. Une erreur de syntaxe peut rendre votre site inaccessible (erreur 500). Testez chaque modification une par une.

Structure du .htaccess WordPress par défaut

# BEGIN WordPress
# [!] Ne jamais modifier ce bloc manuellement —
# WordPress le régénère automatiquement
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress

# Vos règles personnalisées s'ajoutent ICI, en dehors du bloc WordPress

HTTPS et redirections propres

<IfModule mod_rewrite.c>
  RewriteEngine On

  # HTTP → HTTPS (uniquement si votre SSL est actif)
  RewriteCond %{HTTPS} off
  RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

  # www → non-www (choisissez l'un ou l'autre, pas les deux)
  RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
  RewriteRule ^ https://%1%{REQUEST_URI} [R=301,L]
</IfModule>
Attention aux 301 : Les redirections 301 sont permanentes et mises en cache par les navigateurs. Testez d'abord avec un 302 (temporaire), puis passez en 301 une fois validé.

Sécurité WordPress spécifique

Protéger wp-admin

# Restreindre l'accès wp-admin à votre IP (recommandé)
<Files wp-login.php>
  Order Deny,Allow
  Deny from all
  Allow from VOTRE_ADRESSE_IP
</Files>

# Si IP dynamique, limiter les tentatives (nécessite mod_reqtimeout)
# Alternative : utiliser un plugin de sécurité type Wordfence

Bloquer xmlrpc.php — Vecteur d'attaque majeur

# Désactiver xmlrpc.php (inutile sauf si vous utilisez une app mobile WP)
<Files xmlrpc.php>
  Require all denied
</Files>

Protéger wp-config.php et .htaccess

# Empêcher l'accès direct aux fichiers sensibles
<FilesMatch "(wp-config\.php|\.htaccess|\.htpasswd|readme\.html|license\.txt)$">
  Require all denied
</FilesMatch>

# Bloquer la navigation dans les répertoires
Options -Indexes

Bloquer les scans automatiques

<IfModule mod_rewrite.c>
  RewriteEngine On

  # Bloquer les User-Agents de scanners connus
  RewriteCond %{HTTP_USER_AGENT} (nikto|sqlmap|havij|netsparker|acunetix) [NC]
  RewriteRule .* - [F,L]

  # Bloquer les requêtes sans User-Agent (bots malveillants)
  RewriteCond %{HTTP_USER_AGENT} ^$
  RewriteRule .* - [F,L]

  # Bloquer les injections SQL en paramètres GET
  RewriteCond %{QUERY_STRING} (union.*select|insert.*into|drop.*table) [NC]
  RewriteRule .* - [F,L]
</IfModule>

Headers de sécurité HTTP

<IfModule mod_headers.c>
  # Empêcher le clickjacking
  Header always set X-Frame-Options "SAMEORIGIN"

  # Empêcher le MIME type sniffing
  Header always set X-Content-Type-Options "nosniff"

  # Protection XSS basique (legacy, remplacé par CSP)
  Header always set X-XSS-Protection "1; mode=block"

  # Contrôle du referrer
  Header always set Referrer-Policy "strict-origin-when-cross-origin"

  # HSTS — Force HTTPS pour 1 an (n'activer que si HTTPS 100% stable)
  # Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"

  # Supprimer l'en-tête révélant Apache/PHP
  Header unset X-Powered-By
  ServerSignature Off
</IfModule>

Performances via .htaccess

Compression GZIP

<IfModule mod_deflate.c>
  AddOutputFilterByType DEFLATE text/html text/css
  AddOutputFilterByType DEFLATE application/javascript
  AddOutputFilterByType DEFLATE application/json
  AddOutputFilterByType DEFLATE image/svg+xml
  AddOutputFilterByType DEFLATE font/woff font/woff2
</IfModule>

Cache navigateur optimisé

<IfModule mod_expires.c>
  ExpiresActive On

  # HTML : toujours revalider
  ExpiresByType text/html                 "access plus 0 seconds"

  # CSS/JS : 1 an (avec versioning ?v=X.X dans les URLs)
  ExpiresByType text/css                  "access plus 1 year"
  ExpiresByType application/javascript    "access plus 1 year"

  # Images : 1 an
  ExpiresByType image/webp                "access plus 1 year"
  ExpiresByType image/jpeg                "access plus 1 year"
  ExpiresByType image/png                 "access plus 1 year"
  ExpiresByType image/svg+xml             "access plus 1 year"

  # Fonts : 1 an
  ExpiresByType font/woff2                "access plus 1 year"
</IfModule>

Sauvegarde et bonnes pratiques

  • Sauvegardez votre .htaccess actuel avant chaque modification via FTP ou le gestionnaire de fichiers cPanel/DirectAdmin.
  • Testez immédiatement après chaque bloc ajouté — n'attendez pas d'avoir tout ajouté.
  • Vérifiez les logs Apache si une erreur 500 survient : /var/log/apache2/error.log
  • Validateur en ligne : httpd-online.codepad.org pour vérifier la syntaxe.
  • Avec un plugin de cache comme WP Rocket, la majorité des optimisations .htaccess sont gérées automatiquement — préférez le plugin pour éviter les conflits.