Получил "Блокировать загрузку смешанного активного содержимого" на веб-сайте HTTP

проблема

Я занимаюсь разработкой веб-сайта, использующего протокол HTTP. В разработке я использую Webpack с ним webpack-dev-server, который обслуживает страницу локально на http://localhost:9090.

Я был удивлен, увидев в Firefox 58 следующую ошибку смешанного содержимого о загрузке файла шрифта. Это странно для меня, потому что страница обслуживается с использованием HTTP, а не HTTPS, и я думал, что ошибки смешанного контента ограничены только страницами HTTPS.

'Blocked loading mixed active content "http://localhost:9090/b1aa06d82e70bbd5a14259a94c9bbb40.ttf"

Я узнал, что источником ошибки является видеоролик YouTube, встроенный в <iframe> на странице (<iframe src="https://www.youtube.com/embed/...>). Как только я удаляю встраивание YouTube, ошибка исчезает с консоли.

Я не понимаю этого поведения, потому что он не вложен HTTPS iframe, который делает этот запрос шрифта, а внешнюю страницу HTTP (контекст просмотра на верхнем уровне)!

Резюме

Внешняя страница (контекст просмотра верхнего уровня) используется с использованием HTTP. Только встроенный iframe извлекается с использованием HTTPS. HTTP-запрос для файла шрифта, который делает внешняя страница (а не встроенного iframe), создает ошибку смешанного содержимого в консоли Firefox 58.

Примеры кода

Чтобы дать рабочий пример, я создал 2 ручки на Plunker, которые обслуживаются через HTTP и импорт (сам сайт Plunker, а не мой код). Шрифт WOFF шрифт Awesome через HTTP.

Пример. С ошибкой, в которой встроен YouTube iframe, встроенный поверх HTTPS, возникает следующая ошибка в консоли Firefox 58: Blocked loading mixed active content "http://plnkr.co/css/font/Font-Awesome-More.woff".

Пример Без ошибки, который является тем же самым кодом, который только удаляет iframe, не вызывает ошибок.

Вопросы

  • Как вы можете иметь смешанный контент на веб-сайте, загружаемом с использованием протокола HTTP? Я думал, что смешанный контент может существовать только на сайтах, загружаемых с помощью HTTPS. Требует ли какой-либо ресурс через HTTPS (например, встраивание YouTube) делает весь контент необходимым для смешанного содержимого HTTP?
  • Как я могу исправить ошибку? Я не планирую обслуживать веб-сайт через HTTPS, и я хочу, чтобы мои шрифты правильно загружались на рабочем HTTP-сервере.

Ответ 1

Похоже, что Firefox кэширует шрифты и пытается выполнить запрос на кешированный шрифт с использованием URL-адреса, из которого первоначально был доставлен шрифт. Это приводит к ошибке смешанного содержимого.

Я видел эту проблему с шрифтами удивительных шрифтов, когда я развернул веб-приложение на сервере с HTTPS, который я разработал на локальном сервере с HTTP. При запросе отчетов удаленных сайтов Firefox:

Blocked loading mixed active content "http://localhost:8080/fontawesome-webfont.woff2"

Это произвело на меня впечатление, потому что в этом веб-приложении отсутствует запрос на localhost, закодированный в этом веб-приложении.

В вашем примере шрифт загружается

http://plnkr.co/css/apps/editor-1.6.1.css

который является url(../font/Font-Awesome-More.woff)

Один из CSS или скриптов, загружаемых iframe, должен затем попытаться загрузить этот шрифт, возможно, используя динамически сконструированный URL.

Я ничего не знаю о стратегии кэширования шрифтов, реализованной в Firefox, возможно, они идентифицируют шрифт по его названию, но одно из решений, которое я нашел для моего случая, - это "Забыть об этом сайте" в истории Firefox.

Решением для вашего дела может быть переход на HTTPS

Ответ 2

Я была такая же проблема. Я разрешил его, используя относительный путь вместо абсолютного пути.

Поскольку мои шрифты вызываются из этого CSS "/styles/my.css", а мои шрифты располагаются в "/fonts/Open_Sans..."

До (с ошибками FF):

@font-face {
  font-family: "Open Sans";
  src: url("/fonts/Open_Sans/OpenSans-Light.woff2") format("woff2"),
  url("/fonts/Open_Sans/OpenSans-Light.woff") format("woff");
  font-weight: 300;
}

После (без ошибок FF):

@font-face {
  font-family: "Open Sans";
  src: url("../fonts/Open_Sans/OpenSans-Light.woff2") format("woff2"),
  url("../fonts/Open_Sans/OpenSans-Light.woff") format("woff");
  font-weight: 300;
}

Ответ 3

Поскольку у вас проблемы с Firefox, следуйте их документации, как исправить сайт с заблокированным смешанным контентом:

Как исправить ваш сайтEdit

Лучшая стратегия избежания смешанного блокирования контента заключается в том, чтобы обслуживать весь контент как HTTPS вместо HTTP.

Для своего домена, обслуживайте весь контент как HTTPS и исправляйте свои ссылки. Часто версия содержимого HTTPS уже существует, и для этого требуется просто добавить "s" к ссылкам - http://в https://.

Однако в некоторых случаях путь может быть неверным для соответствующих носителей. Для решения этой проблемы есть онлайн, а также автономные инструменты (в зависимости от вашей операционной системы), такие как linkchecker.

Для других доменов используйте версию HTTPS сайта, если она доступна. Если HTTPS недоступен, вы можете попытаться связаться с доменом и спросить, смогут ли они сделать контент доступным через HTTPS.

Ответ 4

Я столкнулся с этой проблемой в результате того, что мои живые и промежуточные серверы являются HTTPS, а моя локальная /dev-копия - HTTP.

Я решил это, создав свой CSS динамически и используя встроенные data: шрифты в CSS, а не ссылки на URL. Это удаляет любую информацию о URL-адресе, связанную с шрифтом, и, таким образом, позволяет избежать любого возможного загрязнения кеша.

В моем случае я использовал PHP, но это может быть изменено на любой серверный язык.

<?php
// Declare this as a CSS file for the browser
header('Content-type: text/css');

/*
 * Respond with 304 if the content was served recently
 *
 * The logic here is:
 *
 * We get a IMS date in the request e.g. 21:00 (Then)
 * We look at the current time e.g. 21:30 (Now)
 *
 * So (Now - Then) must be < 60 * 60
 */
if(isset($_SERVER['HTTP_IF_MODIFIED_SINCE']))
{
    $thenTime = strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']);
    if(time() - $thenTime < 60 * 60)
    {
        header('HTTP/1.1 304 Not Modified');
        exit;
    }
}

// Tell the client the resource was modified on the last hour
$modifiedDate = gmdate('D, d M Y H:00:00 T', time());
header('Last-Modified: ' . $modifiedDate);

?>
@font-face {
  font-family: 'Open Sans';
  font-style: normal;
  font-weight: 300;
  src: local('Open Sans Light'),
       local('OpenSans-Light'),
       url(data:application/x-font-woff;charset=utf-8;base64,<?php echo base64font('open-sans-light.woff') ?>) format('woff');
}

@font-face {
  font-family: 'Open Sans';
  font-style: normal;
  font-weight: 400;
  src: local('Open Sans'),
       local('OpenSans'),
        url(data:application/x-font-woff;charset=utf-8;base64,<?php echo base64font('open-sans-normal.woff') ?>) format('woff');
}

<?php

function base64font($file)
{
    $fontFolder = realpath(__DIR__ . '/../fonts');
    $data = file_get_contents($fontFolder . '/' . $file);
    $base64 = base64_encode($data);

    return $base64;
}

Я установил заголовок 304, если он уже загружен в браузер. Вам не обязательно иметь это, но это улучшит производительность, если вы это сделаете. Определения шрифтов редко меняются, поэтому вы можете сделать эту задержку дольше на сайтах с высоким трафиком.