HTTPS 在 HTTP 的基礎上增加了SSL/TLS加密,提供了更加安全的傳輸協議。儼然已經屬於各大網站的標配。有贊作為一個 SaaS 平臺,涉及到使用者的商品,交易,支付等關鍵性流程。支援全站 HTTPS,提高網站安全是我們的基礎保障。本文關注的事情包括: 瞭解 HTTPS 基礎原理,切換 HTTPS 需要切換的內容,如何監控和實際操作,以及遇到的一些難點。
一、基本原理
在原有 HTTP 握手的基礎上,增加了證照的驗證,進行了加密,這樣我們傳輸資料就有安全的保證。解決的問題包括運營商劫持
、中間人攻擊
、釣魚網站
、提升SEO
等。具體流程如下:
- 客戶端傳送“ClientHello”訊息,訊息包含 SSL 的版本、客戶端支援的加密套件和資料壓縮演算法及隨機數1。
- 伺服器響應“ServerHello”訊息,訊息包含選定的加密套件、選定的資料壓縮方法、會話標識,數字證照及另一個隨機數2。
- 客戶端( Web 瀏覽器)驗證伺服器的SSL數字證照的有效性,不通過則提示警告。
- 客戶端傳送“客戶端金鑰交換”訊息。此訊息包含 pre-master secret(用於生成對稱加密金鑰生的隨機數3)。
- 客戶端使用一系列加密運算將 [隨機數1 隨機數2 隨機數3] 轉化為 master secret,其中將派生出所有用於加密和訊息認證的金鑰。
- 伺服器使用一系列加密運算將 [隨機數1 隨機數2 隨機數3] 轉化為 master secret,其中將派生出所有用於加密和訊息認證的金鑰。
- 客戶端發出“更改密碼規範”通知伺服器端之後使用協商好的對稱加密演算法及金鑰通訊。
- 伺服器發出“更改密碼規範”通知客戶端之後使用協商好的對稱加密演算法及金鑰通訊。
- SSL握手結束,使用對稱加密演算法進行加密通訊。
二、 切換需要涉及的資源和服務
當你開始著手切換成 HTTPS 的工作時,首先你需要明確你要處理的內容有什麼? 一般來說你需要梳理以下內容:
- 部署到cdn的靜態資源,js、css
- 圖片資源
- 主域及其次級域名的數量
- 是否有第三方資源,比如廣告、視訊等接入
- api 呼叫,是否動態返回 HTTP 業務
- 提供的對外服務
關於第1點,靜態資源基本會收斂於少數域名,服務也基本會由第三方 cdn 服務商提供。 對應的服務提供商處開啟 HTTPS 支援。
動態引入靜態資源
<link rel="stylesheet" href="${loadStaticContent(www/css/main.min.css)}">
<script type="text/javascript" src="${loadStaticContent(www/js/main.min.js)}"></script>
複製程式碼
在早期全站載入靜態資源過程中, 應該自定義前端模板方法去動態載入 js,css。 防止寫死域名情況。後期在全站切 cdn 域名時,就可以直接使用新的 HTTPS 域名,一刀切,修改模板方法引入域名和路徑。
關於第2點,圖片來源一般分為兩種,站內圖片和站外圖片。站內圖片,基本會使用第三方 cdn 服務。可以統一開啟 HTTPS。而站外圖片一般的來源可能包括:開發寫死,對接第三方服務(類似淘寶導購),連結型圖片上傳未儲存到自己的服務。
css動態引入圖片
.loading {
background-image: image-cdn('/logo_loading.png');
}
複製程式碼
假設使用了 sass 等工具,站內圖片可以在 css 中引入 cdn 域名載入方法。統一替換。
老圖片問題
對於老的 HTTP 資料圖片資料,業務訪問可知的情況下,需要跑指令碼重新上傳。對於上傳圖片元件若傳入的是 HTTP 圖片,應該考慮重新上傳支援。
關於第3點,主域及其次級域名,可以通過統計 nginx 日誌上 HTTP 的流量(awk日誌)。獲取現有站點 HTTP 流量的 pv 訪問表。得到需要HTTPS的域名的數量。確認切換 HTTPS 順序和工期,考慮因素包括:請求量的大小
、業務的輕重緩急
、業務切換 HTTPS 難度
、各域名功能
等方面。在確定站點基本情況後,需要和各業務方交流以上方面問題。得出各域名切換的時間節點。
關於第4點,第三方資源引入問題。
- 視訊應該使用引入支援 HTTPS 的視訊資源,比如騰訊視訊。
- 外站不支援 HTTPS 圖片,應該考慮重傳為站內圖片。
- 廣告對接,一般是引入第三方廣告指令碼,第三方指令碼做什麼事情,都屬於第三方指令碼的工作, 所以需要指令碼提供方提供 HTTPS 服務
原則上第三方資源應該是 HTTPS 的,如果不是,我們可能就需要儲存到自己的服務上或者通過服務端轉發。否則必然是 HTTPS 的環境下,引入 HTTP 的情況
關於第5點,屬於業務範疇,前端走 api 方式的呼叫,返回值中針對頭像、展示圖片等圖片方式,如果經過模板層可以考慮加模板方式統一替換成 HTTPS,直接拼裝成的字串。可以提供統一方法替換。
關於第6點 ,比如你有 api 等對外服務。早期開放了 HTTP 呼叫的口子,那麼很遺憾。我們能做的事情是通過公告、郵件等方式告知第三方,我們在特定時間後就不在支援 HTTP 服務,希望第三方支援 HTTPS 呼叫。或者如果安全性不重要的話,那麼就同時支援HTTP/HTTPS呼叫。蘋果 HTTPS 的公告 App Transport Security就是很好的例子,而實際上 app 內部還是留了開啟 HTTP 請求的設定。
以上是需要我們處理的大部分內容。在推進全站 HTTPS 問題之前,做好這步梳理準備。包括了調研
、確認切換範圍
、瞭解業務切換難易程度
、確定工作的時間安排和參與人員
。注:各部分工作設定好 deadline,會對你有非常大的幫助。
三、切換 HTTPS 中的注意點
站內 HTTPS 資源準備完畢後,就可以考慮將各站點切換成HTTPS。操作層面需要注意以下幾點:
相對協議
程式碼層面對明顯寫死的 HTTP 協議進行修改。修改成相對協議
是不錯的選擇
<img src="//domain.com/img/logo.png">
<script src="//www/js/libs/jquery/1.4.2/jquery.js"></script>
複製程式碼
相對協議下,當你訪問 HTTPS 網站時,請求 HTTPS 資源。否則 HTTP。這樣方案上更具有靈活性,可以考慮內網先進行 HTTPS 的測試,對外網使用 HTTP。 假設 HTTPS 方案出現問題時,可退回到 HTTP。
301 與 302區別
當頁面所有資源都切換成 HTTPS,迴歸測試後。可考慮 HTTP 訪問網站時, nginx 302
重定向到 HTTPS。強制切換。上線後可經過幾天到一週的觀察。(流量大和複雜業務需要更久)業務穩定, 無異常及使用者反饋情況。可以強制301
切換。
302和301的區別就在於:302重定向是臨時的,下次瀏覽器訪問同樣是訪問原連結。而301重定向是持久的。下次瀏覽器會直接訪問新連結。所以當確定某域名下已經實現了 HTTPS,可採用301重定向。
Content-Security-Policy
當某站點已經切換成了 HTTPS 。假設後期還是有開發人員引入 HTTP 的情況。我們應該採用哪種 CSP 策略防止呢?
block-all-mixed-content
, 強制阻止頁面內HTTP載入
<meta http-equiv="Content-Security-Policy" content="block-all-mixed-content">
複製程式碼
但是實際上,阻止 HTTP 載入不是我們的目的,後期開發中
引入 HTTP 的行為可能是疏漏造成的,我們可以理解成實際上資源已經可以支援 HTTPS 的。 所以可以採用另一種CSP策略: upgrade-insecure-requests
<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">
複製程式碼
該策略下會產生以下兩種效果
- 站點內的 HTTP 請求,都會 HTTPS 的方式發起。
- 所有連線跳轉都會以 HTTPS 的方式開啟。
這種策略顯然更加友好。當網站已經確認強制使用了 HTTPS,就可以加入該方法。
測試環境是否啟用 HTTPS
從測試便利性角度,測試環境可以提供 Http。但實際上為了和正式環境一致應該用 HTTPS 測試更合理。因為上述推薦使用相對協議,所以測試環境本身是可以提供 Http/HTTPS 兩種方案的。
四、遇到的難點
全站 HTTPS 由於域名和業務等因素影響,切換過程中必然會遇到許多難點。 主要表現在業務方來源和使用者訪問來源:
- 基礎介面呼叫方太多,同時存在前端直接呼叫或者後端業務層呼叫的情況,需要介面提供方定位介面真實呼叫位置。
- 一些介面呼叫沒有
referer
,referer 對於前端定位流量來源能夠提供非常大的幫助。但是有一些頁面的 Http 訪問不存在 referer,這種情況可能由於使用者儲存該頁面連結或者從其他來源進入網站頁面丟失等造成。假設頁面經過 HTTPS 測試通過,可以通過強制切換成 HTTPS 解決。 - 客戶端介面老版本請求 HTTP 情況,根據使用者的量,判斷是否放棄老版本的呼叫。否則無法根除該流量的 HTTP
- 第三方請求公司提供的 HTTP 服務, 告知第三方規定時間內升級。
除了以上的幾個顯性難點外,其實還有些隱性難點,比如需要與業務方約定明確強制切換的 deadline,介面升級、服務改造遷移、老介面複雜性等各種問題都會拖延各實施方的進度。只有強制的 deadline 切換才保住全站 HTTPS 的推進進度。
寫在最後,本文主要是圍繞推動公司全站 HTTPS 的一些心得。更多的是以一個專案推動方的角度考慮如何推動事情的落地。原理,內容,執行,難點。這幾個核心流程把握住。我們才能做到更加有條理的實施。同時全站流量切換成 HTTPS,其實只是工作的開始。之後的 HTTPS 效能優化、異常 HTTP 流量監控、HTTPS 可用性監控等都是接下來應該去不斷推進的工作。
本文首發於有贊技術部落格。