WordPress ❤ HTTPS

Когда я узнал о том, что в скором времени гугл Хром планирует начать ругаться на опасность сайтов без HTTPS, я решил сделать себе пару бесплатных сертификатов, чтобы мои блоги стали немного безопаснее. Заставить WordPress работать по защищённому протоколу удалось не сразу, и я столкнулся с некоторыми трудностями.
В теории перевести WordPress на HTTPS очень просто. Достаточно в админке сменить протокол в адресе сайта с http://kel.mn на https://kel.mn

wordpress-ssl-httpsНесмотря на то, что главная страница отдавалась по HTTPS, бо́льшая часть контента блокировалась браузером из-за того, что движок настойчиво продолжал отдавать css и js по http. Как только я это увидел, сразу пустился на поиски плагина, который бы всё это исправил. Из опробованных могу вспомнить «WordPress HTTPS» и «Force SSL». Первый ломал сайт после внесения настроек, второй — сразу после активации. Оба расширения создавали циклическую переадресацию и были абсолютно бесполезны.

После этого я начал искать способ, с помощью которого можно было бы подменить протокол во время генерации ссылки на файл. Кое-что мне всё же удалось найти, в результате чего одна или две таблицы стилей стали грузиться, но не более того.

Позже я натолкнулся на плагин «Fix SSL/Non-SSL Links», который, по задумке, должен был определять протокол, по которому происходит загрузка страницы, и, в соответствии с ним, отдавать все остальные стили, картинки и скрипты. Этот плагин также не заработал, но натолкнул меня на мысль. В нём использовалась функция is_ssl(), которая и должна была определять протокол. Это стандартная функция WordPress, потому её неправильное функционирование заставило меня задуматься: «А что, если WordPress не получает информацию об используемом протоколе?»

И в самом деле, на тестовой странице с phpinfo() не выводилось никакой информации о том, что используется защищённый протокол. Apache, работающий бэкендом, не получал от Nginx информации об этом.

Выходит, что вся проблема была в неправильно настроенном проксировании:

location / {
	proxy_pass http://127.0.0.1:8080/;
	proxy_set_header X-Real-IP $remote_addr;
	proxy_set_header X-Forwarded-for $remote_addr;
	proxy_set_header Host $host;
	proxy_connect_timeout 60;
	proxy_send_timeout 90;
	proxy_read_timeout 90;
	proxy_redirect off;
	proxy_set_header Connection close;
	proxy_pass_header Content-Type;
	proxy_pass_header Content-Disposition;
	proxy_pass_header Content-Length;
}

Как видно, для Apache здесь нет ни малейшей зацепки.

Каким же образом можно исправить проблему?

Первый вариант: настройка WordPress

В Nginx к остальным параметрам проксирования добавить строчку:
proxy_set_header X-Forwarded-Protocol "https";

Затем в wp-config.php добавить следующую проверку:

// Проверка https
	if( !empty( $_SERVER['HTTP_X_FORWARDED_PROTOCOL'] ) ) {
$_SERVER['HTTPS'] = 'on';
}
Этот код нужно добавлять перед строкой
require_once(ABSPATH . ‘wp-settings.php’);

После этого WordPress понял, что работает по HTTPS, и начал отдавать контент правильно.

Второй вариант: настройка Apache

В Nginx к остальным параметрам проксирования добавить строчку
proxy_set_header X-Forwarded-Proto $scheme;

Затем в виртуалхосте Apache добавить следующую проверку:
SetEnvIf X-Forwarded-Proto https HTTPS=on

Этот вариант так же помогает WordPress правильно угадать протокол.

Вывод

При добавлении нового функционала веб-сервера, в данном случае — HTTPS, стоит уделить особое внимание мелким отличиям между текущей конфигурацией и той, которую предстоит использовать. Если бы я сразу научил Apache правильно определять протокол, этой записи здесь не было.

Из двух представленных вариантов я рекомендую выбирать второй, потому что при такой настройке правильно определять протокол сможет не только WordPress, а вообще всё, что обрабатывается Apache.

4 комментария WordPress ❤ HTTPS

  1. Дмитрий

    Единственный на практике оказавшийся полезным пост по теме. Все дружно копипастят и рерайтят друг у друга одни и те же схемы, которые для wp не работают. Понятно, что у школьников на шарных хостингах нет вариантов настроить сервер, но зачем переписывать с чужих слов, не убедившись, что это дает результат. В общем, спасибо!

  2. Иван

    Поддерживаю предыдущего автора .Три дня потратил на поиск решения,только это помогло.Использовал первый вариант. Связка Nginx (front-end) + Apache (backend).
    Спасибо добрый человек

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *