網站從 HTTP 切換到 HTTPS 那一刻,大多數人以為工作已告結束。憑證裝好、瀏覽器顯示鎖頭、Google Search Console 也沒報錯,看起來一切正常。但 WordPress SSL 設定其實只完成了一半——HSTS 啟用時機、混合內容(Mixed Content)警告的清理,以及 Let’s Encrypt 自動續約的穩定性,這三塊才是決定「真正安全」還是「差一點安全」的分水嶺。
這篇文章的範圍鎖定這三個方向,逐一說明機制、風險,以及遇到問題時該從哪裡著手。
HSTS 啟用的時機與不可逆風險
HSTS(HTTP Strict Transport Security,HTTP 嚴格傳輸安全)是一組加在伺服器回應標頭裡的指令,告訴瀏覽器「這個網域未來只准走 HTTPS,不管使用者輸入什麼」。聽起來簡單,但它的核心風險藏在「不可逆」三個字裡。
啟用 HSTS 後,瀏覽器會把指令快取到本機,有效期間由 max-age 決定,常見設定是 31536000 秒(365 天)。在這段期間內,即使取消 HTTPS、憑證過期或主機出狀況,瀏覽器仍然拒絕以 HTTP 連入,網站對那些已快取過 HSTS 的訪客來說會直接無法存取——沒有任何繞過的辦法,除非等快取到期或使用者手動清除。
啟用 HSTS 的前提條件要全部到位才能動手。
- 憑證穩定性確認:HTTPS 要運作至少 1 到 2 個月,確認自動續約機制正常,才適合啟用 HSTS。
- 全站重新導向健全:HTTP → HTTPS 的 301 轉址要涵蓋所有子網域,沒有遺漏或例外路徑。
- 子網域全部就緒:如果計畫啟用
includeSubDomains選項,每個子網域都必須有有效的 HTTPS,否則那些子網域同樣會被鎖定。 - preload 慎用:
preload選項會把網域提交到各大瀏覽器的內建清單,從此不論快取是否到期,瀏覽器永遠強制 HTTPS。要從清單移除需要申請,且可能需要數個月才能生效。
WordPress 站台若使用 Really Simple SSL 外掛,HSTS 功能藏在「設定 > SSL」裡的進階標頭選項,預設不啟用,需要手動開啟。開啟前務必確認以上四點已全部達成。
混合內容警告的來源與處理邏輯
網站切換到 HTTPS 後出現混合內容警告,根源幾乎都一樣:頁面已走 HTTPS,但頁面裡有部分資源——圖片、JavaScript、CSS、影片嵌入——仍以 HTTP 協議被呼叫。瀏覽器把這種狀況視為安全漏洞,因為未加密的資源理論上可能在傳輸途中被竄改。
混合內容分兩類,嚴重程度不同。被動混合內容(Passive Mixed Content)指圖片、音訊、影片,瀏覽器通常會載入但顯示警告;主動混合內容(Active Mixed Content)指 JavaScript 和 CSS,因為這類資源能直接操作頁面行為,現代瀏覽器預設會直接封鎖,不是警告而是拒絕執行。
常見來源
WordPress 的混合內容問題通常集中在幾個位置。
- 資料庫裡的硬寫 HTTP 網址:遷移到 HTTPS 時,如果只改了 WordPress 設定裡的「網站網址」,卻沒有批次替換資料庫中的 URL,文章內容、小工具、選單、外掛設定裡的舊連結仍然是 HTTP。
- 外部嵌入資源:YouTube、Vimeo、地圖嵌入若使用舊版
http://嵌入碼,會成為主動或被動混合內容;第三方廣告腳本、追蹤像素、舊版內容傳遞網路(CDN)設定也是常見來源。 - 佈景主題與外掛的硬編碼路徑:部分較舊的佈景主題或外掛在 PHP 原始碼裡寫死
http://開頭的資源路徑,而非使用 WordPress 的home_url()或相對路徑。
Really Simple SSL 的修正機制
Really Simple SSL 的核心功能之一,就是在頁面輸出時用 PHP 的輸出緩衝(Output Buffering)掃描 HTML,把 http:// 開頭的資源網址即時替換成 https://。這個做法對資料庫硬寫問題特別有效,不需要直接動資料庫就能解決大多數警告。
但這個機制有限制。它只能處理「頁面 HTML 輸出」裡的靜態網址,對於由 JavaScript 動態插入的資源、或透過 AJAX 載入的內容,即時替換無法覆蓋。遇到這類情況,需要配合瀏覽器開發者工具的「控制台」或「網路」面板,找出實際觸發的 HTTP 請求來源,再從根本修改程式碼或嵌入碼。
掃描工具方面,外掛內建的掃描功能可以列出已知的問題資源;SSL Labs 的線上檢測(ssllabs.com/ssltest)可驗證憑證設定;瀏覽器的開發者工具則是定位動態混合內容最直接的手段。
Let’s Encrypt 自動續約失敗的排查方向
Let’s Encrypt 憑證有效期 90 天,設計上依賴自動化工具(通常是 Certbot 或主機控制面板的內建機制)在到期前 30 天自動續約。大多數情況下這個流程不需要人工介入,但當它失敗時,往往會在毫無預警的情況下讓網站突然顯示憑證錯誤。
自動續約失敗有幾個常見根因,排查要從下列方向著手。
- DNS 解析問題:Let’s Encrypt 在驗證時需要能從外部存取網域,如果 DNS 設定近期有變更(例如換主機後尚未完全生效),驗證請求可能打到舊 IP,導致失敗。確認方式是從外部網路用
dig或線上 DNS 工具確認域名解析指向正確的伺服器。 - HTTP-01 驗證路徑被封鎖:Certbot 預設使用 HTTP-01 驗證,需要在
http://your-domain/.well-known/acme-challenge/放置暫時驗證檔。若.htaccess有規則把所有 HTTP 請求強制轉址到 HTTPS,或防火牆、CDN 設定封鎖了這個路徑,驗證就會失敗。解決方式是在轉址規則前加例外,讓/.well-known/acme-challenge/的 HTTP 流量直接通過。 - Cron 任務未執行:VPS 或獨立主機環境下,自動續約通常靠系統排程(
cron)觸發。若排程設定被刪除或執行帳號無權限,續約流程根本不會啟動。用crontab -l或systemctl status certbot.timer確認任務是否存在且正常執行。 - 主機控制面板的自動續約設定:使用 cPanel、Plesk 等控制面板的站台,Let’s Encrypt 整合通常由面板自行管理。若憑證顯示無法自動續約,先進入面板的 SSL 管理介面確認設定狀態,再查面板的錯誤日誌,而非直接用 Certbot 指令操作——兩者同時管理同一憑證可能產生衝突。
- 速率限制:Let’s Encrypt 對同一網域每週最多簽發 5 張憑證。若測試期間反覆申請,可能觸發速率限制,導致後續申請全部失敗直到限制解除。這不是系統問題,等待一週或改用 Let’s Encrypt 的 staging 環境測試是正確做法。
收到續約失敗的告警後,最快的確認方式是直接執行 certbot renew --dry-run,它會模擬完整的續約流程但不實際寫入憑證,輸出訊息通常能明確指出失敗原因。排查清楚根因後再執行正式的 certbot renew 即可。
憑證裝好只是起點。HSTS 的謹慎啟用、混合內容的徹底清理,以及自動續約的可靠運作,三者合在一起,才能確保訪客看到的始終是完整、無誤的安全連線。