Dokumentacja

Napraw mieszaną zawartość

Napraw mieszaną zawartość

Mieszana zawartość to strona na https://, która część swoich elementów ładuje zwykłym http://: obraz, skrypt, arkusz stylów, czcionkę lub osadzoną ramkę. Sama strona jest szyfrowana, ale te elementy nie, więc każdy w sieci mógłby je podejrzeć lub podmienić. Przeglądarki reagują same: skrypty, style i ramki od razu blokują (slider przestaje działać, formularz traci wygląd, mapa znika), obrazy i wideo próbują podnieść do https:// i pomijają je, jeśli się nie uda, a stronę pokazują bez kłódki.

Prawie zawsze bierze się z adresów wpisanych w treść lub kod, zanim strona przeszła na HTTPS. Lista kontrolna strony podaje, ile plików znalazła, i kilka przykładów.

Skąd się bierze

Źródło Typowy przykład
treść w bazie danych obrazy wstawione do wpisów lata temu jako http://example.com/wp-content/uploads/…
motyw lub szablon logo lub skrypt z pełnym adresem http:// wpisanym w kodzie
page builder Elementor, Divi lub WPBakery przechowują bezwzględne adresy i wygenerowany CSS
osadzenia i kod zewnętrzny stary widżet, mapa, czcionka lub licznik dołączony jako http://…
aplikacja framework za proxy, który myśli, że żądanie przyszło po HTTP, i buduje linki http://

Linki (<a href="http://…">) nie są mieszaną zawartością: niczego nie ładują do strony.

Sprawdź sam

Najszybciej w przeglądarce. Otwórz stronę, naciśnij F12 (lub Cmd+Option+I na Macu), przejdź do zakładki Console i przeładuj. Każdy problem pojawia się jako linia w rodzaju:

Mixed Content: The page at 'https://example.com/' was loaded over HTTPS, but requested an insecure image 'http://example.com/logo.png'.

Lista z wiersza poleceń (zamiast example.com wpisz swoją stronę):

curl -s https://example.com | grep -oiE '<(img|script|iframe|source|video|audio|embed)[^>]+src="http://[^"]+"|<link[^>]+href="http://[^"]+"' | sort -u

Po naprawie: konsola nie pokazuje żadnej linii Mixed Content, a polecenie nic nie wypisuje. Sprawdź kilka różnych typów stron (strona główna, wpis, produkt); problem często jest tylko w starszej treści.

Jak to naprawić

Prawdziwa poprawka to zmiana adresów http:// na https:// tam, gdzie są zapisane. Najpierw upewnij się, że każdy plik naprawdę istnieje pod https:// (otwórz adres z https:// w przeglądarce). Potem wybierz to, do czego masz dostęp.

WordPress

  1. W Settings → General zarówno WordPress Address (URL), jak i Site Address (URL) muszą zaczynać się od https://.
  2. Zamień stare adresy w bazie danych. Najpierw zrób kopię zapasową. Użyj narzędzia, które rozumie zserializowane dane WordPressa; zwykłe SQL REPLACE psuje widżety i ustawienia page buildera.

Z WP-CLI najpierw na próbę, potem naprawdę:

wp db export before-https.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

Bez wiersza poleceń użyj darmowej wtyczki Better Search Replace (Tools → Better Search Replace): wyszukaj http://example.com, zamień na https://example.com, zaznacz wszystkie tabele i najpierw uruchom na próbę (dry run).

  1. Elementor: Elementor → Tools → Replace URL robi to samo dla danych Elementora. Potem na zakładce General tego samego ekranu wygeneruj ponownie jego CSS. Inne buildery też przechowują wygenerowany CSS; wyczyść go w ich ustawieniach.
  2. Motyw i widżety: przeszukaj pliki motywu potomnego, Appearance → Customize → Additional CSS oraz widżety tekstowe i HTML pod kątem http://.
  3. Wyczyść wszystkie pamięci podręczne (WP Rocket, LiteSpeed Cache, cache hostingu, Cloudflare).

Jako szybkie obejście darmowa wtyczka Really Simple SSL (obecnie Really Simple Security) ma naprawiacz mieszanej zawartości, który podczas wysyłania strony przepisuje http:// na https://. Ukrywa objaw; adresy zostają w bazie, więc zamianę i tak wykonaj.

Statyczny HTML

Przeszukaj wszystkie pliki pod kątem adresów, które ładują coś przez HTTP:

grep -rnE '(src|href|action)="http://|url\(.?http://' --include='*.html' --include='*.css' --include='*.js' .

Pomiń zwykłe linki (<a href="http://…">); nie są mieszaną zawartością. Resztę zmień na https://. Dla plików z Twojej domeny jeszcze lepsza jest ścieżka od katalogu głównego (/images/logo.png): działa na każdej domenie i protokole. Jeśli plik zewnętrzny nie jest dostępny przez HTTPS, pobierz go i serwuj sam albo go zastąp.

Laravel

Za load balancerem, Cloudflare lub innym proxy Laravel dostaje żądanie po HTTP, a url(), asset() i route() budują adresy http://. Zaufaj proxy w bootstrap/app.php, żeby Laravel czytał X-Forwarded-Proto:

->withMiddleware(function (Middleware $middleware) {
    $middleware->trustProxies(at: '*');
})

Jeśli adresy IP Twojego proxy są stałe, zastąp nimi '*'. Ustaw też APP_URL=https://example.com w .env, bo używają go zadania w kolejce i e-maile. Potem poszukaj wpisanych na sztywno http:// w widokach Blade i zapisanej treści.

Cloudflare

Przejdź do SSL/TLS → Edge Certificates i włącz Automatic HTTPS Rewrites. Cloudflare przepisuje wtedy w przekazywanym HTML adresy http:// na https:// dla zasobów, o których wie, że działają przez HTTPS, w tym dla Twojej domeny.

Pomaga tylko przy ruchu przez proxy (pomarańczowa chmurka) i nie naprawi zasobu, który nie ma wersji HTTPS. Adresy zostają w Twojej treści, więc popraw je także u źródła.

nginx

Jako obejście na czas porządkowania treści dyrektywa upgrade-insecure-requests każe przeglądarce pobierać każdy zasób strony z http:// przez https://. W bloku server dla HTTPS (/etc/nginx/sites-available/example.com na Debianie i Ubuntu, /etc/nginx/conf.d/example.com.conf na Rocky, Alma i CentOS):

add_header Content-Security-Policy "upgrade-insecure-requests" always;
sudo nginx -t && sudo systemctl reload nginx

Jeśli już wysyłasz nagłówek Content-Security-Policy, dopisz do niego upgrade-insecure-requests; zamiast wysyłać drugi.

Apache i LiteSpeed

Jako obejście ta sama dyrektywa upgrade-insecure-requests, w wirtualnym hoście strony albo w .htaccess w katalogu głównym strony (działa też na LiteSpeed):

<IfModule mod_headers.c>
    Header always set Content-Security-Policy "upgrade-insecure-requests"
</IfModule>

Z dostępem do serwera przeładuj potem: sudo apachectl configtest && sudo systemctl reload apache2 (httpd na Rocky, Alma i CentOS).

Uwaga: upgrade-insecure-requests i przepisywanie Cloudflare sprawiają, że przeglądarka ładuje pliki przez HTTPS, ale adresy http:// wciąż są w stronie, więc lista kontrolna wymienia je, dopóki nie zmienisz ich u źródła. Plik, który nie istnieje pod https://, zamiast ładować się niebezpiecznie, w ogóle się nie załaduje.

Platformy hostowane

Shopify, Wix, Squarespace i Webflow serwują własne pliki przez HTTPS. Mieszana zawartość bierze się tam z tego, co dodano ręcznie: bloku z własnym kodem lub osadzeniem, skryptu wklejonego do nagłówka, obrazu wstawionego przez adres albo kodu motywu (w Shopify: Online Store → Themes → ⋯ → Edit code). Znajdź ją konsolą przeglądarki i zmień adres w tym bloku na https://.

Potwierdź poprawkę

Przeładuj stronę z otwartą konsolą przeglądarki i uruchom ponownie polecenie curl z sekcji Sprawdź sam, potem otwórz cel w PulseKeeper i kliknij Sprawdź teraz na zakładce Lista kontrolna.