Błąd mixed content występuje wtedy, gdy początkowy kod strony ładuje się bezpiecznie przez protokół HTTPS, ale część jej zasobów, takich jak obrazki, skrypty czy arkusze stylów, jest wciąż pobierana przez niezabezpieczone połączenie HTTP. Aby go naprawić, musisz zlokalizować niezabezpieczone linki w kodzie lub bazie danych i masowo podmienić ich przedrostki z http:// na https://. Przeglądarki internetowe traktują takie witryny jako częściowo niebezpieczne. Użytkownik widzi wtedy pękniętą kłódkę lub ostrzeżenie o braku prywatności. To natychmiast odstrasza ruch.
Kiedy wdrażasz certyfikat bezpieczeństwa, oczekujesz zielonej kłódki i spokoju. Rzeczywistość na produkcji zazwyczaj weryfikuje te plany bardzo boleśnie. Zrobiliśmy kiedyś migrację dla małego portalu osiedlowego na łódzkiej Retkini. Wszystko przepięte na poziomie serwera, reguły w pliku htaccess dodane, testy przechodzą. Wbijamy na front, a kłódki brak. Okazało się po prostu, że jeden z redaktorów wkleił baner reklamowy pizzerii, ciągnąc go na sztywno z HTTP z jakiegoś starego serwera na home.pl. Szlag człowieka trafia przy takich wdrożeniach na koniec dnia pracy w piątek. Przeglądarka natychmiast podnosi alarm. Blokuje skrypt. Użytkownik dostaje komunikat o zagrożeniu.
Skąd dokładnie bierze się mieszana zawartość po instalacji SSL?
Problem wynika wprost z budowy protokołu przesyłania danych. Kiedy wpisujesz adres witryny, serwer nawiązuje zaszyfrowane połączenie TLS. Przesyła dokument tekstowy. W tym dokumencie znajdują się odwołania do innych plików. Jeśli programista lub system CMS zapisał te odwołania używając pełnego adresu z przedrostkiem HTTP, przeglądarka posłusznie wykonuje polecenie. Próbuje pobrać plik bez szyfrowania. A to łamie całą koncepcję bezpieczeństwa. Połączenie przestaje być prywatne.
W zdecydowanej większości przypadków winne są stare wpisy w bazie danych. WordPress, Joomla czy Drupal zapisują absolutne ścieżki do plików graficznych w treści postów. Zmieniasz adres witryny w ustawieniach głównych. System generuje nowe linki poprawnie. Ale tysiące starych artykułów nadal trzymają w sobie twardo zakodowane odnośniki HTTP. To generuje błąd. Innym powodem są przestarzałe motywy graficzne. Twórcy szablonów często podpinają zewnętrzne biblioteki JavaScript lub fonty od Google bezpośrednio w kodzie nagłówka. Zostawiają stary protokół. My potem musimy to ręcznie wycinać z plików PHP.
Na bazie analizy logów z serwerów Nginx w polskich software house’ach z lutego bieżącego roku wynika, że blisko sześćdziesiąt procent zgłoszeń o niedziałającym SSL-u dotyczy właśnie twardo zakodowanych linków w starych motywach. To plaga. Klienci kupują paczki na giełdach, instalują je u siebie i dziwią się, że ruch spada. A Google tnie zasięgi za brak kłódki bez litości.
Jakie są rodzaje błędu mixed content na stronach WWW?
Przeglądarki dzielą ten problem na dwie odrębne kategorie. Różnią się one stopniem zagrożenia i reakcją silnika renderującego. Mamy zawartość pasywną i aktywną.
Zawartość pasywna to pliki, które nie mogą zmienić zachowania witryny. Należą do nich pliki graficzne, materiały wideo, pliki dźwiękowe oraz proste obiekty osadzone. Jeśli obrazek ładuje się po HTTP, atakujący typu man-in-the-middle może go przechwycić i podmienić w locie. Wyobraź sobie sklep internetowy. Ktoś podmienia zdjęcie butów na obraźliwy mem. To psuje wizerunek. Ale nie kradnie haseł. Dlatego Chrome czy Firefox zazwyczaj wyświetlają takie strony, pokazując jedynie ostrzeżenie w pasku adresu. Kłódka znika. Pojawia się trójkąt lub przekreślenie.
Zawartość aktywna to zupełnie inna waga problemu. Wchodzą w to skrypty JavaScript, arkusze CSS, ramki iframe i obiekty Flash. Tutaj ryzyko rośnie drastycznie. Przechwycony skrypt pozwala hakerowi na przejęcie całej sesji użytkownika. Może on sczytywać znaki wpisywane z klawiatury. Kradnie dane logowania. Podmienia numery kont bankowych w formularzach przelewu. Przeglądarki wiedzą o tym doskonale. I dlatego reagują agresywnie.
| Typ zasobu | Przykłady plików | Reakcja przeglądarki | Skutek dla użytkownika |
| Pasywny (Wyświetlany) | .jpg, .png, .mp4, .mp3 | Ostrzeżenie w pasku adresu, brak kłódki | Strona działa, ale wygląda na niezabezpieczoną |
| Aktywny (Wykonywalny) | .js, .css, .woff, iframe | Całkowita blokada pobrania pliku | Strona się sypie wizualnie, funkcje nie działają |
Zablokowanie zasobów aktywnych oznacza katastrofę na froncie. Rozjeżdża się układ kolumn. Znikają style. Przyciski przestają reagować na kliknięcia. Użytkownik widzi białą kartę z czarnym tekstem rodem z lat dziewięćdziesiątych. To natychmiastowy spadek konwersji do zera. A ty szukasz przyczyny w kodzie.
Dlaczego darmowe skanery online często się mylą?
Wielu początkujących administratorów wrzuca adres domeny do pierwszego lepszego skanera SSL z wyszukiwarki. Narzędzie mieli temat przez minutę. Wyrzuca zielony komunikat o braku błędów. Ty idziesz na kawę. A klienci dalej zgłaszają problemy na maila. Dlaczego tak się dzieje? Boty skanujące zazwyczaj sprawdzają tylko stronę główną. Nie klikają w podstrony. Nie logują się do kokpitu. Nie rozwijają dynamicznych menu ładowanych przez AJAX. Jeśli masz wkurwiający problem z jednym obrazkiem ukrytym głęboko w regulaminie sklepu, automat tego nie wyłapie. Trzeba to sprawdzić ręcznie. To jedyna metoda dająca pewność.
Jak sprawdzić w konsoli co wywołuje błąd HTTPS?
Zamiast polegać na zewnętrznych gadżetach, użyj narzędzi wbudowanych w przeglądarkę. Włączasz Chrome. Wchodzisz na swoją witrynę. Wciskasz klawisz F12 na klawiaturze. Otwiera się panel deweloperski. Wybierasz zakładkę Console. To tam maszyna wypluwa wszystkie błędy na czerwono i żółto. Szukasz komunikatów zaczynających się od słów „Mixed Content”.
Silnik podaje ci na tacy dokładny adres zasobu, który psuje sprawę. Zobaczysz tam wpis mówiący o tym, że strona została załadowana przez HTTPS, ale zażądała niezabezpieczonego pliku. Chrome od razu poinformuje cię, czy zasób został zablokowany, czy tylko wywołał ostrzeżenie. Kopiujesz ten link. Wiesz już, czego szukać w bazie. Zaglądasz też do zakładki Network. Odświeżasz widok. Sortujesz zapytania po kolumnie Scheme. Wszystko co ma tam wpisane HTTP musi zostać poprawione. Brak wyjątków.
Prawda jest zresztą absolutnie taka, że najwięcej czasu zajmuje zawsze namierzenie winowajcy, a nie sama naprawa. Piszemy ten skrypt migracyjny o 3 nad ranem, puszczamy na bazę, a rano i tak zgłasza się klient, bo mu ikona koszyka zniknęła. Okazuje się, że ikona była wciągana z zewnętrznego CDN-a, który akurat nie miał ważnego certyfikatu dla subdomeny. I cała robota stoi.
Jak naprawić błąd mixed content w środowisku WordPress?
Masz wyciągniętą listę błędnych linków. Teraz trzeba je fizycznie zmienić. Jeśli strona ma kilka podstron, wchodzisz w edytor HTML i dopisujesz literę „s” do adresu. Sprawa załatwiona. Ale przy portalu z tysiącem artykułów ręczna edycja to absurd. Musisz uderzyć bezpośrednio w bazę danych MySQL.
Wielu ludzi idzie na skróty i instaluje wtyczki typu Really Simple SSL. Wtyczka przechwytuje żądania w locie za pomocą bufora wyjściowego PHP i podmienia linki przed wysłaniem ich do przeglądarki. To działa. Ale to proteza. Obciąża procesor serwera przy każdym odświeżeniu strony. Wymusza dodatkowe operacje. Zdecydowanie lepszym podejściem jest trwała poprawa wpisów w bazie. Wtyczki zostaw amatorom.
Najpierw zrób pełną kopię zapasową bazy danych. Jeden zły znak w zapytaniu SQL i kładziesz cały portal. Kiedy masz backup, użyj narzędzia WP-CLI z poziomu terminala SSH. To najszybsza metoda. Wpisujesz komendę search-replace. Podajesz stary adres HTTP. Podajesz nowy adres HTTPS. System przelatuje przez wszystkie tabele i podmienia ciągi znaków. Działa to błyskawicznie.
Jeśli nie masz dostępu do SSH, użyj skryptu Search Replace DB od interconnect/it. Wrzucasz katalog ze skryptem na serwer przez FTP. Odpalasz go w przeglądarce. Podajesz dane do bazy. Skrypt radzi sobie z danymi zserializowanymi. To główny problem w WordPressie. Zwykłe zapytanie SQL UPDATE zepsuje zserializowane tablice w tabeli wp_options. Skrypt od interconnect/it najpierw rozpakowuje dane, podmienia tekst, a potem pakuje je z powrotem przeliczając długość łańcucha znaków. Genialne i proste.
Co zrobić z linkami zakodowanymi w szablonie?
Baza danych wyczyszczona. Odświeżasz front. Błąd nadal wisi. To oznacza, że linki siedzą na twardo w plikach PHP. Odpalasz klienta FTP. Pobierasz cały katalog motywu na dysk. Używasz edytora kodu, na przykład VS Code. Wciskasz CTRL+SHIFT+F. Wpisujesz swój stary adres z protokołem HTTP. Edytor przeszukuje setki plików w kilka sekund. Pokazuje ci dokładnie numer linii w pliku header.php lub functions.php. Zmieniasz adres. Zapisujesz. Wysyłasz z powrotem na serwer.
Czasami zewnętrzne systemy reklamowe wymuszają ładowanie skryptów po HTTP. Jeśli wydawca nie obsługuje połączeń szyfrowanych, masz spory problem. Musisz zrezygnować z takiej reklamy. Nie ma kompromisów w kwestii bezpieczeństwa frontu. Zostawienie jednego skryptu śledzącego zepsuje kłódkę na całej domenie.
Warto też dodać odpowiedni nagłówek dyrektywy Content Security Policy. Możesz wymusić na przeglądarce automatyczną próbę podniesienia protokołu. Wrzucasz do pliku htaccess regułę wysyłającą nagłówek Upgrade-Insecure-Requests. Przeglądarka widząc link HTTP, sama w locie zamienia go na HTTPS przed wysłaniem żądania. To rozwiązuje problem z linkami, których nie potrafisz zlokalizować. Oczywiście działa to tylko wtedy, gdy docelowy serwer faktycznie obsługuje ruch szyfrowany. Jeśli nie obsługuje, zasób po prostu się nie załaduje.
Wpływ mieszanej zawartości na pozycjonowanie w Google
Algorytmy wyszukiwarek nie tolerują zaniedbań w obszarze certyfikatów. Posiadanie poprawnego wdrożenia TLS to oficjalny czynnik rankingowy. Jeśli robot Googlebot wchodzi na twoją podstronę i widzi zablokowane skrypty, traktuje witrynę jako zepsutą. Nie wyrenderuje jej poprawnie. Nie zobaczy treści wygenerowanych przez JavaScript. Twoje pozycje lecą w dół.
Użytkownicy też robią swoje. Wchodzą z wyników wyszukiwania. Widzą czerwoną kłódkę. Natychmiast klikają przycisk wstecz. Współczynnik odrzuceń rośnie. Google dostaje sygnał, że wynik był słaby i niebezpieczny. Konsekwencje są brutalne dla biznesu opierającego się na ruchu organicznym. Tracisz zaufanie i widoczność jednocześnie.
Sprawdź raporty w Google Search Console. W zakładce dotyczącej jakości strony znajdziesz raport o HTTPS. Silnik wskaże ci tam dokładnie, które adresy URL nie spełniają wymogów bezpieczeństwa. Traktuj ten raport jako priorytetową listę zadań na poniedziałek. Ignorowanie tego to oddawanie klientów konkurencji za darmo.
Zaloguj się teraz na swój serwer. Odpal konsolę deweloperską. Przeklikaj pięć najważniejszych podstron w swoim serwisie i sprawdź komunikaty błędów. Zrób kopię bazy. Uruchom podmienianie linków. Przestań polegać na wtyczkach maskujących problem w locie. Czysta baza to podstawa stabilnego działania każdej witryny w sieci.
Najczęściej zadawane pytania (FAQ)
- Czym różni się zawartość aktywna od pasywnej przy błędzie mixed content?
Zawartość pasywna to obrazki i wideo, które przeglądarka załaduje pomimo braku HTTPS, pokazując jedynie ostrzeżenie. Zawartość aktywna to skrypty i arkusze stylów, które zostaną całkowicie zablokowane w obawie przed kradzieżą danych. - Czy wtyczka Really Simple SSL rozwiązuje problem na stałe?
Nie. Wtyczka ta jedynie przechwytuje żądania w locie i maskuje problem, obciążając przy tym serwer. Najlepszą metodą jest fizyczna zmiana linków w bazie danych z HTTP na HTTPS. - Gdzie najszybciej znajdę błędne linki ładujące się po HTTP?
W konsoli deweloperskiej przeglądarki Chrome lub Firefox (klawisz F12). W zakładkach Console oraz Network znajdziesz dokładne ścieżki do niezabezpieczonych zasobów. - Dlaczego kłódka znika tylko na niektórych podstronach?
Ponieważ błąd dotyczy konkretnych elementów osadzonych w treści danej podstrony, np. starego zdjęcia w konkretnym wpisie na blogu, a nie globalnych ustawień serwera. - Czy błąd mixed content wpływa na pozycje w Google?
Tak. Brak pełnego zabezpieczenia obniża ocenę jakości strony (Page Experience), co bezpośrednio przekłada się na spadki w wynikach wyszukiwania organicznego. - Jak bezpiecznie zmienić linki w bazie WordPressa?
Należy użyć narzędzia WP-CLI z komendą search-replace lub specjalnego skryptu do podmiany danych zserializowanych, zawsze po wcześniejszym wykonaniu pełnej kopii zapasowej bazy.
Bibliografia
1. Google Search Central – https://developers.google.com
2. Mozilla Developer Network – https://developer.mozilla.org
3. WordPress Codex – https://wordpress.org
4. Nginx Documentation – https://nginx.org
5. Let’s Encrypt – https://letsencrypt.org
