Po włączeniu HTTPS strona WordPressa może otwierać się pod adresem https://, a mimo to przeglądarka nadal zgłaszać Mixed Content. Oznacza to, że dokument został pobrany przez HTTPS, ale przynajmniej jeden z jego zasobów nadal odwołuje się do adresu HTTP.
Źródłem może być obraz zapisany w treści wiele lat temu, arkusz CSS motywu, skrypt wtyczki, font, adres zapisany w ustawieniach albo kod wygenerowany dynamicznie.
Nie zaczynaj od globalnego „zamień http na https”. Najpierw ustal dokładny URL problematycznego zasobu i miejsce, z którego WordPress go generuje.
Co właściwie oznacza Mixed Content?
Mixed Content występuje wtedy, gdy bezpieczny dokument HTTPS próbuje załadować zasób przez niezabezpieczone HTTP. Przeglądarka widzi wtedy dwie różne warstwy bezpieczeństwa w obrębie jednej strony.
W praktyce problem może dotyczyć między innymi:
- obrazów,
- arkuszy CSS,
- JavaScriptu,
- fontów,
- iframe'ów,
- plików audio i wideo,
- żądań wykonywanych przez skrypty.
Nie każdy typ zasobu jest traktowany przez przeglądarkę identycznie. Część może zostać automatycznie podniesiona do HTTPS, a bardziej ryzykowne żądania mogą zostać zablokowane. Dlatego objawem bywa zarówno ostrzeżenie w konsoli, jak i brakujący element strony.
Najpierw znajdź dokładny adres HTTP
Najbardziej użytecznym punktem startowym jest konsola deweloperska przeglądarki. Komunikat Mixed Content zwykle wskazuje adres dokumentu HTTPS oraz konkretny zasób zażądany przez HTTP.
Warto zapisać pełny URL i typ zasobu. To od razu zawęża poszukiwania.
| Problematyczny URL | Gdzie szukać źródła |
|---|---|
Obraz z wp-content/uploads | Treść wpisu, dane attachmentu, widget lub konfiguracja wtyczki |
| Plik motywu lub pluginu | Kod komponentu, ustawienia albo dynamiczne generowanie URL-a |
| Zewnętrzny font/skrypt | Motyw, page builder, Custom CSS/JS, integracja zewnętrzna |
| Stara domena po migracji | Baza WordPressa, konfiguracja komponentu, cache |
Jeżeli problem dotyczy tylko jednej podstrony, zwykle nie ma potrzeby przeszukiwania całej instalacji. Najpierw sprawdź elementy charakterystyczne właśnie dla tego widoku.
Po migracji stare adresy często pozostają w bazie
Zmiana adresu WordPressa nie przepisuje automatycznie każdego URL-a zapisanego przez wszystkie wtyczki i motywy. Stare odwołania mogą pozostać w treści wpisów, ustawieniach, metadanych albo własnych tabelach pluginów.
Problem jest szczególnie widoczny po przejściu:
- z HTTP na HTTPS,
- ze starej domeny na nową,
- ze środowiska stagingowego na produkcję.
Proste pole tekstowe można zmienić stosunkowo łatwo, ale baza WordPressa zawiera również dane serializowane. Dlatego mechaniczny globalny REPLACE() wykonany bez rozpoznania struktury danych może uszkodzić wartości przechowujące informacje o długości ciągów.
Do migracji URL-i lepiej używać mechanizmu, który rozumie dane WordPressa i serializację, zamiast wykonywać niekontrolowaną zamianę we wszystkich tabelach.
Przed zbiorczą zamianą wykonaj backup i najpierw sprawdź wynik w trybie testowym. WP-CLI wp search-replace obsługuje dane serializowane i umożliwia --dry-run; przy migracji domeny trzeba również uważać, aby nie zmieniać pola guid tylko dlatego, że zawiera stary adres.
Nie każdy adres HTTP znajduje się w treści wpisu
Jeżeli wyszukiwanie starego URL-a w treściach niczego nie znajduje, trzeba sprawdzić inne źródła generowania HTML.
Adres może pochodzić z:
- ustawień motywu,
- page buildera,
- widgetu lub bloku,
- Custom CSS albo Custom HTML,
- opcji wtyczki,
- menu,
- kodu szablonu,
- zewnętrznego API lub feedu.
Dobrym tropem jest charakter adresu. Jeśli URL zawiera ścieżkę konkretnego pluginu, zacznij od tego komponentu. Jeśli wskazuje stary CDN lub staging, szukaj konfiguracji odpowiedzialnej za generowanie assetów.
Nie należy również zakładać, że problem musi znajdować się w bazie. Hardcoded URL w PHP, CSS lub JavaScript pozostanie taki sam niezależnie od poprawnych ustawień WordPressa.
HTTPS w WordPressie i HTTPS zasobu to dwie osobne rzeczy
Nawet jeśli WP_HOME, WP_SITEURL i certyfikat TLS są poprawne, strona nadal może generować odwołania do zasobów przez HTTP.
Jeżeli problematyczny URL prowadzi do własnej domeny, zwykle warto sprawdzić, dlaczego WordPress nadal generuje stary protokół.
Jeżeli jest to zasób zewnętrzny, najpierw sprawdź, czy rzeczywiście działa pod https://. Zamiana protokołu na ślepo niczego nie naprawi, gdy zewnętrzny serwer nie obsługuje TLS albo plik pod nowym adresem nie istnieje.
W takim przypadku właściwym rozwiązaniem może być zmiana dostawcy zasobu, lokalne hostowanie pliku, aktualizacja integracji albo usunięcie niepotrzebnego odwołania.
Cache może pokazywać Mixed Content mimo poprawionej konfiguracji
Po naprawieniu źródła starego URL-a problem może pozostać w wygenerowanej wcześniej wersji strony. Dotyczy to cache WordPressa, cache serwera, CDN oraz statycznych plików CSS lub JavaScript tworzonych przez builder lub plugin optymalizacyjny.
Dlatego po poprawce warto rozdzielić dwie sytuacje:
- źródłowy HTML lub CSS nadal zawiera
http://— problem nie został jeszcze naprawiony u źródła; - źródło jest poprawne, ale użytkownik otrzymuje starą kopię — trzeba odświeżyć odpowiednią warstwę cache.
Czyszczenie wszystkich cache przed znalezieniem przyczyny utrudnia diagnozę. Lepiej najpierw wskazać źródło adresu, potem poprawić konfigurację i dopiero na końcu odświeżyć wygenerowane kopie.
Upgrade-Insecure-Requests może ukryć objaw, ale nie zastępuje naprawy
Przeglądarki i polityka Content Security Policy mogą pomagać w automatycznym podnoszeniu części żądań z HTTP do HTTPS. Dyrektywa CSP upgrade-insecure-requests instruuje przeglądarkę, aby przed wysłaniem żądania traktowała odpowiednie niezabezpieczone URL-e jak HTTPS.
Jeżeli dany zasób nie jest rzeczywiście dostępny przez HTTPS, automatyczne podniesienie protokołu zakończy się błędem — przeglądarka nie wróci wtedy do wersji HTTP.
Może to być użyteczna warstwa przejściowa lub zabezpieczająca, ale nie powinna zastępować uporządkowania adresów generowanych przez witrynę.
Jeżeli w bazie lub szablonie nadal zapisujesz stare http://, problem pozostaje w danych. Może wrócić przy innym sposobie renderowania, eksporcie treści albo integracji, która nie korzysta z tej samej polityki CSP.
Bezpieczna procedura naprawy Mixed Content
- Otwórz problematyczną stronę i znajdź dokładny URL HTTP w konsoli lub Network.
- Ustal typ zasobu. Obraz, CSS, JS, font, iframe czy request aplikacyjny?
- Sprawdź, kto generuje ten adres. Treść, motyw, wtyczka, baza czy zewnętrzna integracja?
- Jeżeli to stary URL po migracji, ustal bezpieczny sposób jego zamiany.
- Przed zbiorczą zmianą wykonaj backup i dry-run.
- Nie wykonuj ślepego SQL REPLACE na danych serializowanych ani pola guid przy typowej migracji domeny.
- Jeżeli zasób jest zewnętrzny, potwierdź, że jego wersja HTTPS rzeczywiście działa.
- Popraw źródło adresu.
- Dopiero potem wyczyść właściwą warstwę cache.
- Ponownie sprawdź konsolę i Network.
Jeżeli Mixed Content pojawił się po migracji hostingu, warto także sprawdzić, czy strona korzysta już wyłącznie z docelowego hosta i protokołu. Pomóc może diagnostyka domeny przed migracją.
Jeżeli równocześnie występuje pętla HTTPS, najpierw rozwiąż konflikt przekierowań opisany w poradniku ERR_TOO_MANY_REDIRECTS w WordPressie.
Najważniejsze wnioski
- Mixed Content oznacza, że strona HTTPS odwołuje się do co najmniej jednego zasobu przez HTTP;
- najpierw trzeba znaleźć dokładny URL problematycznego zasobu, a dopiero potem szukać źródła;
- stare adresy mogą pozostać w treści, metadata, options, tabelach pluginów albo kodzie;
- globalny SQL
REPLACE()może być niebezpieczny dla danych serializowanych WordPressa; - przed zbiorczą migracją URL-i warto wykonać backup i
--dry-run, a typowa migracja domeny nie powinna mechanicznie zmieniać polaguid; - zewnętrzny zasób trzeba najpierw sprawdzić pod kątem realnej obsługi HTTPS;
- cache może przechowywać starą wersję HTML, CSS lub JS już po poprawieniu konfiguracji;
upgrade-insecure-requestsnie zapewnia fallbacku do HTTP, jeśli zasób nie działa po HTTPS;- naprawę warto zakończyć ponownym sprawdzeniem konsoli i pełnego zestawu żądań strony.
Źródła
- MDN Web Docs — Mixed content — definicja Mixed Content i zachowanie przeglądarek.
- MDN Web Docs — upgrade-insecure-requests — automatyczne podnoszenie niezabezpieczonych żądań do HTTPS i brak fallbacku do HTTP.
- WordPress Developer Resources — Editing wp-config.php — konfiguracja adresów WordPressa.
- WordPress Developer Resources — Migrating WordPress — zmiana domeny i zasada zachowania pola GUID.
- WP-CLI — wp search-replace — obsługa serializowanych danych,
--dry-runi pomijanie wybranych kolumn. - WordPress Developer Resources — maybe_serialize() — serializacja danych przechowywanych przez WordPress.
- WordPress Developer Resources — maybe_unserialize() — odczyt danych serializowanych.