1. 程式人生 > >關於啟用 HTTPS 的一些經驗分享(三)

關於啟用 HTTPS 的一些經驗分享(三)

文章目錄

提醒:本文最後更新於 930 天前,文中所描述的資訊可能已發生改變,請謹慎使用。

關於「啟用 HTTPS 的經驗分享」這個話題,我已經寫過兩篇文章:第一篇主要介紹 HTTPS 如何與一些較新的安全規範配合使用,面向的是現代瀏覽器;第二篇主要討論啟用 HTTPS 過程中,在 SSL 版本、Cipher Suite、證書、SSL 擴充套件(如 SNI)等方面可能遇到的問題,以及在老舊瀏覽器下如何取捨。本文做為本系列最後一篇,我想補充一些啟用 HTTPS 過程中的注意事項。

資源替換

HTTPS 網頁中載入的 HTTP 資源被稱之為 Mixed Content(混合內容),我在之前的文章中詳細介紹了 Optionally-blockable

Blockable 兩類 Mixed Content,也介紹了各種瀏覽器對 Mixed Content 的載入策略。為了最好的使用者體驗,HTTPS 網站不要出現任何 Mixed Content。換句話說,HTTPS 頁面中所有資源都必須替換為 HTTPS 的。

程式碼層的替換比較簡單,但一些存在資料庫中的文字(例如商品描述中的圖片地址)就很容易遺漏,需要特別注意。

如果你的網站只打算支援 HTTPS,將所有外鏈資源(CSS、JS、圖片、音訊、字型檔案、非同步介面等等)直接替換為 HTTPS 地址,再把網站 HTTP 請求重定向到 HTTPS 即可。

當前很多支援 HTTPS 的網站出於各種原因,針對老舊瀏覽器或特殊網路還是允許通過 HTTP 訪問。這時候,強烈建議讓所有資源服務都同時支援 HTTP/HTTPS 訪問。這樣只要頁面在使用這些資源時省略協議部分,瀏覽器就能根據主頁面協議型別來自動選擇 HTTP/HTTPS 資源。例如:

<img src="https://example.com/static/img/blog/ququ.jpg" />
=>
<img src="//example.com/static/img/blog/ququ.jpg" />

針對現代瀏覽器,還可以通過 upgrade-insecure-requests 這個 CSP 指令,讓瀏覽器自動替換。更多說明,詳見這裡

省略 URL 協議有個風險點:個別行動網路提供商篡改頁面時,會將這種寫法的 URL 改壞,導致資源無法訪問。詳見《詭異問題排查之「DataURI 引發的血案」》這篇文章。

服務端代理

在啟用 HTTPS 的實際過程中,本站的靜態資源和介面相對容易改造,畢竟都可控。但很多第三方資源或介面就是不提供 HTTPS,那就只能在服務端做一層 HTTPS 代理。

服務端代理另外一個典型應用是用來解決跨域問題。通常代理本身要做的工作不多,直接用 Nginx 做反向代理,或者用 Lua、Node.js 等語言構建輕量中轉服務都是不錯的選擇。但也有幾點需要注意:

  • 代理對請求 Referrer、被代理的 URL 都需要做好白名單機制;
  • 代理會造成第三方通過 REMOTE_ADDR 拿到的是代理 IP,很可能導致這個 IP 被限制請求頻率或被封;
  • 代理只能拿到自己域名下的 Cookie,需要從其它域獲取 Cookie 的第三方介面被代理後可能不能正常工作;

另外,對於頁面上通過 iframe 嵌入的第三方 HTTP 頁面,如果要做 HTTPS 代理,還需要修改頁面裡的所有資源連結,很容易出問題。對於這種情況,強烈建議聯絡第三方修改或者換產品方案,不要在 HTTPS 代理上耗費太多精力。

還有一個不那麼常見的問題順便說下:如果頁面表單的 action 地址使用了 HTTP 地址,會導致 Chrome 位址列綠色小鎖消失。下面是一個簡單示例:

<form action="http://imququ.com"></form>

最後,再討論一個第三方介面由本地服務提供的特殊場景(例如 Android APP 在本地開一個 127.0.0.1 的 HTTP 服務,給網頁呼叫)。這個服務幾乎不可能升級為 HTTPS,顯然也無法使用服務端代理。對於這個問題,我在《利用圖片傳輸資料的另類思路》這篇文章裡,提供了一種能用但不完美的解決方案。

Referrer

目前大部分瀏覽器,在發生協議降級時預設不傳送 Referrer 資訊,最典型的場景就是從 HTTPS 頁面點連結跳到 HTTP 網站時,瀏覽器並不會在請求頭中帶上 Referer 欄位。對於給第三方導流的網站,這一點肯定無法接受。

針對現代瀏覽器,這個問題可以通過給頁面加上下面這個 meta 標籤來解決:

<meta name="referrer" content="always" />

有關這個 meta 的更多用法,請參考《Referrer Policy 介紹》這篇文章。

針對老舊瀏覽器,這個問題可以通過在本站部署 HTTP 跳轉服務來解決,藉助 HTTP 頁面把 Referrer 傳給第三方。

另外,本文同時出現了 ReferrerReferer 兩種寫法,如果對此有困惑,推薦閱讀《Referrer 還是 Referer?》。

連通性

很多網站在啟用 HTTPS 之後,都會接到無法訪問的使用者反饋。除去自身配置問題(我在《從啟用 HTTP/2 導致網站無法訪問說起》一文中列舉了常見的配置錯誤)之外,很有可能是 HTTPS 連通性受到了干擾。

最常見的干擾是運營商劫持了域名 DNS 解析,這種劫持伺服器一般會將使用者請求反代到源網站,再在響應裡夾帶私貨。在 HTTP 時代,這種劫持多半隻會造成頁面出現廣告,網站還能用;而升級到 HTTPS 後,由於身份認證機制的存在,劫持伺服器無法成功反代第三方網站(成功實施 HTTPS 中間人攻擊的條件請看《三種解密 HTTPS 流量的方法介紹》),從而導致網站完全不可用。

我們最近在移動端做過一個統計:對比在 HTTP 網站載入本域 HTTP/HTTPS 空圖片的失敗率(我們對失敗的定義是觸發圖片的 error 事件,或者超過 9s 仍未觸發 load 事件),HTTPS 要高出三個百分點。

對於 HTTPS 請求失敗日誌,還可以進一步分析,比如找出是哪些運營商 / 地域的 HTTPS 聯通性比較差,從而有針對性做一些策略。由於每個業務情況都不相同,這裡只丟擲問題,詳細的統計資料和應對措施不在這裡討論。

本文先寫到這裡,有新的注意事項我會隨時補充進來。最後我想說的是,啟用 HTTPS 並不複雜,雖然會遇到各種各樣的問題,但都能找到對應的解決方案,所需的無非就是決心、耐心和細心。在現代瀏覽器中,越來越多的新功能都限定在 HTTPS 下才能使用,HTTPS 也是部署 HTTP/2 的先決條件。HTTPS 和 HTTP/2 已經成為 WEB 服務的標配,趕緊行動起來吧。

--EOF--

提醒:本文最後更新於 930 天前,文中所描述的資訊可能已發生改變,請謹慎使用。