La dernière version de WordPress m’a posé pas mal de petits soucis… Après le problème de traduction dont je vous parlais l’autre jour et une régression sur la gestion des liens dans l’éditeur (plus possible de définir l’attribut title des liens), résolu via un plug-in, on m’a signalé que les images insérées dans les articles sont désormais servies par défaut en HTTPS…
En effet, il y a apparemment eu un changement dans le comportement du gestionnaire de média. Alors qu’auparavant les médias étaient toujours insérés avec des liens basés sur l’adresse définie dans la configuration de WordPress (adresse en HTTP dans mon cas), ils sont désormais insérés en reprenant le protocole utilisé pour accéder à l’administration. Comme j’utilise l’option FORCE_SSL_ADMIN pour que l’administration soit accessible uniquement en HTTPS, les images se retrouvent donc insérés en HTTPS. Mon certificat SSL étant jusqu’à présent un certificat auto-signé, les visiteurs n’ayant jamais accédé au site en SSL se retrouvent alors sans images et sans alerte du navigateur les invitant à accepter le certificat. Ballot…
La solution « simple » serait bien entendu de passer à un certificat SSL signé par une autorité reconnue, mais il se pose alors toujours un problème de cohérence : les anciens articles vont continuer à servir les images en HTTP même lorsqu’ils sont accédés en HTTPS (provoquant une alerte au niveau du navigateur) et les nouveaux articles serviront toujours les images en HTTPS même lorsqu’ils sont activés en HTTP. De plus, les liens entre articles insérés via l’éditeur continuent pour leur part à être des liens HTTP, quelque soit le protocole utilisé pour l’accès à l’interface…
J’ai donc décidé de sortir l’artillerie lourde : utiliser à nouveau le système de filtres de WordPress pour modifier les liens et les références aux images, et les adapter au protocole utilisé par le visiteur. Là encore, c’est au final assez simple, grâce au filtre the_content, appliqué à chaque fois qu’un contenu d’article ou de page est affiché. Il n’y a donc qu’à écrire une fonction modifiant tous les liens dans des attributs src ou href pour les servir avec le bon protocole, quand il s’agit de liens internes (avec le même nom de domaine que celui du site) :
1 2 3 4 5 6 7 8 9 10 11 12 |
// Force le protocole sur les attributs src et img pointant vers le domaine du site function forceContentURLScheme($content) { $host = $_SERVER["HTTP_HOST"]; $newScheme = "http"; $oldScheme = "https"; if (is_ssl()) { $newScheme = "https"; $oldScheme = "http"; } return preg_replace("#(src|href)=\"$oldScheme://$host#", "\\1=\"$newScheme://$host", $content); } add_filter("the_content", "forceContentURLScheme"); |
Une fois ce code placé dans un plugin ou un mu-plugin, tous les liens internes dans les articles seront en HTTP lorsque le site sera visité en HTTP et en HTTPS lorsque le site sera visité en HTTPS.
Il est également possible d’appliquer cette transformation à l’ensemble de la page, et pas seulement au contenu des posts (pratique si vous avez par exemple des liens « en dur » dans les menus) ou si vous voulez mettre le HTTPS par défaut tout en permettant le HTTP (dès lors que l’URL du site est en HTTPS dans les options de WordPress, les liens vers les articles dans les pages de catégorie et d’archive seront forcément en HTTPS) en utilisant un output buffer PHP (WordPress est prévu pour permettre l’ouverture de plusieurs couches d’output buffer et les fermera automatiquement tous en fin de traitement) et en appliquant la transformation dessus :
1 2 3 4 |
function forcePageURLScheme(){ if (!is_admin()) ob_start('forceContentURLScheme'); } add_action('wp', 'forcePageURLScheme', 10, 0); |
L’application à l’ensemble de la page via l’output buffer peut éventuellement entrer en conflit avec d’autres plug-ins utilisant le mécanisme d’output buffer de PHP. Dans ce cas, essayer de diminuer ou augmenter le paramètre 10 (qui définit l’ordre d’application des filtres).
J’ai finalement aussi décidé de passer à un certificat SSL signé par une autorité de certification, mais pour l’instant le laisse le HTTP accessible. À terme, je mettrais peut-être une redirection forcée vers la version HTTPS.
3 réflexions sur « WordPress : forcer l’utilisation de HTTP/HTTPS pour les images »