Перейти к содержанию
Innovialabs

Ошибки смешанного содержимого (mixed content): причины и решение

Практика3 мин

Коротко

Mixed content — это когда HTTPS-страница загружает скрипты, стили или картинки по обычному HTTP; найдите их в DevTools, замените адреса на HTTPS в коде и базе данных, а upgrade-insecure-requests добавьте как страховку.

Что такое смешанное содержимое

Mixed content возникает, когда страница открыта по HTTPS, а часть её ресурсов — скрипты, стили, картинки, шрифты, iframe, запросы к API — всё ещё запрашивается по http://. Сама страница зашифрована, а эти запросы нет, и злоумышленник в той же сети может их прочитать или подменить.

Браузеры реагируют по-разному:

  • Активное содержимое (скрипты, стили, iframe, запросы fetch/XHR) блокируется. Именно поэтому после перехода на HTTPS у сайта внезапно «слетают» стили или перестаёт работать виджет.
  • Пассивное содержимое (картинки, аудио, видео) современные браузеры обычно сами пытаются загрузить по HTTPS. Если по HTTPS ресурс недоступен, он просто не загрузится, а у замка в адресной строке может появиться предупреждение.

Решение всегда одно: каждый ресурс должен запрашиваться по HTTPS.

Откуда оно берётся после перехода на HTTPS

  • Жёстко прописанные адреса в шаблонах, CSS (background: url(http://...)) и JavaScript.
  • База данных CMS хранит абсолютные ссылки в записях, настройках и виджетах. WordPress, например, сохраняет http://-адреса картинок прямо в тексте поста.
  • Неверный адрес сайта в конфиге — приложение строит ссылки от базового URL, который всё ещё начинается с http://.
  • Reverse proxy или балансировщик снимает TLS, приложение видит обычный HTTP-запрос и генерирует http://-ссылки. Ему нужно доверять заголовку X-Forwarded-Proto.
  • Сторонние вставки — старые счётчики, виджеты и CDN, добавленные много лет назад.

Как найти небезопасные ресурсы

  1. Откройте страницу и DevTools → Console. Каждый заблокированный или переписанный запрос отображается как предупреждение «Mixed Content» с точным адресом.
  2. Проверьте вкладку Network: смотрите на схему всех запросов, включая те, что появляются после кликов и прокрутки.
  3. Поищите по коду:
grep -rn "http://" --include=*.{html,css,js,php,tsx,twig} .
  1. Поищите в дампе базы данных свой домен с http://.
  2. На больших сайтах обойдите все страницы краулером или соберите отчёты через Content Security Policy в режиме report-only: браузер будет сообщать о нарушениях, ничего не блокируя.
Content-Security-Policy-Report-Only: default-src https: data: blob: 'unsafe-inline' 'unsafe-eval'; report-uri /csp-report

Как исправить в коде

  • Замените http:// на https:// у всех ресурсов, которые это поддерживают.
  • Для своих файлов используйте пути от корня (/assets/app.css) — они автоматически наследуют схему страницы.
  • Вынесите базовый URL в переменную окружения и укажите в ней https://.
  • За прокси включите в фреймворке доверие к заголовкам прокси, чтобы приложение знало, что исходный запрос был по HTTPS.
  • Если у стороннего ресурса нет HTTPS-версии, замените его или разместите у себя. Безопасного способа оставить его как есть не существует.

Как исправить в базе данных CMS

Не запускайте обычный SQL REPLACE по таблицам WordPress: часть значений хранится как сериализованные PHP-массивы с длиной строк, и слепая замена их ломает. Используйте инструмент, который понимает сериализацию, например WP-CLI:

wp db export backup.sql
wp search-replace 'http://example.com' 'https://example.com' --all-tables --dry-run
wp search-replace 'http://example.com' 'https://example.com' --all-tables

Сначала обязательно сделайте резервную копию и посмотрите результат пробного запуска. Затем обновите адрес сайта в настройках и очистите все кэши (страниц, CDN, объектный), иначе продолжит отдаваться старый HTML.

upgrade-insecure-requests как страховка

Директива CSP upgrade-insecure-requests заставляет браузер переписывать все http://-запросы ресурсов страницы на https:// до отправки. Добавьте её заголовком ответа:

add_header Content-Security-Policy "upgrade-insecure-requests" always;

Или meta-тегом в <head>:

<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">

Помните об ограничениях:

  • Она не делает ресурс доступным по HTTPS. Если у сервера нет HTTPS-версии, запрос упадёт.
  • Она не переписывает ссылки на другие сайты, по которым кликает пользователь.
  • Она скрывает проблемы, а не устраняет их, поэтому это страховка, а не исправление.

После наведения порядка включите HSTS, чтобы браузеры всегда открывали ваш домен по HTTPS.

Частые вопросы

Большинство предупреждений исчезнет, но ресурсы без HTTPS всё равно сломаются, а новые http://-ссылки продолжат копиться в базе. Исправьте источники, а директиву оставьте как запасной вариант.

Поможем с этим

Если хотите не разбираться самим, а получить результат — этим мы занимаемся каждый день.

Обсудить проект

Читайте также

Есть идея или задача? Расскажите нам

Ответим в течение рабочего дня и предложим решение. Консультация бесплатная.