隨着網絡安全重要性日益凸顯,越來越多的站點已經全站切換到HTTPS,其中很多HTTPS站點同時將HTTP協議升級到了HTTP/2。作為一只前端,最近一直在學習和應用相關知識點,便總結梳理如下。
一、何為HTTPS、HTTP/2?
HTTPS 全稱Hypertext Transfer Protocol Secure,是一種網絡安全傳輸協議,是在HTTP之下,傳輸層至上,增加了傳輸層安全協議TLS (Transport Layer Security)。HTTPS通過HTTP進行通信,通過TLS加密傳輸數據,對HTTP協議的版本沒有要求,可以是HTTP/1.x,也可以是HTTP/2。
HTTP/2 超文本傳輸協議的第2版(最初命名為HTTP 2.0),簡稱h2(加密連接)或h2c(非加密連接)。HTTP/2 對是否在加密通道上建立連接沒有要求,但為了避免代理和中間設備對數據傳輸的影響,所有支持HTTP/2的瀏覽器都只支持HTTPS信道上的HTTP/2(參見caniuse)。 HTTP/2 的主要目標是提升傳輸性能,減少延遲,提高吞吐量,從而提高頁面性能。
二、為何說HTTPS是安全的?
我們知道HTTP是明文傳輸的,假設A同學與B同學要通信,途徑M同學,就可以被M同學查看並篡改,不能保證數據的安全。我們首先想到的就是加密,AB同學約好密鑰key(因為這里的A、B同學的密鑰是一樣的,這種加密算法稱為對稱加密算法,對應的密鑰稱之為對稱密鑰),將消息加密以后傳輸。這樣是不是就安全了?
然而,網絡中A同學B同學不能像現實生活中一樣,背着人打個電話,偷偷約定好密鑰,不告訴別人。A和B在約定密鑰的時候,還是會途徑M同學。。。
那么如何才能安全的交換對稱密鑰呢?這里使用非對稱加密算法(非對稱加密算法需要兩個密鑰,公開密鑰和私有密鑰,簡稱公鑰和私鑰,如果用公開密鑰對數據進行加密,只有用對應的私有密鑰才能解密;如果用私有密鑰對數據進行加密,那么只有用對應的公開密鑰才能解密)。第一步,A同學使用非對稱加密算法,生成公鑰K1和私鑰K2,將公鑰K1傳給B同學。第二步,B同學自己准備了一個對稱密鑰key,使用公鑰K1加密key,將加密后的key傳給A同學。第三步,A同學用只有自己才知道的私鑰K2解密,得到key的值。之后A和B就可以愉快的使用key加密后的消息來通信了。M同學也不知道他們在聊什么~
也許有人會問,非對稱加密這么好,為什么不用來傳輸消息?因為非對稱加密對計算資源消耗大,對加密內容的有長度限制,不能超過公鑰長度(常用的RSA不能超過256字節),因此只用來做密鑰交換。傳輸消息使用對稱加密算法來加解密。
這樣是不是就安全了呢?有沒有發現有漏洞?如果M跟A通信時偽裝成B,M跟B通信時偽裝成A,與A、B分別進行密鑰交換,那么信息傳輸仍然是不安全的。這就是中間人攻擊。因此在HTTPS建立連接時,還需要CA認證,通過驗證CA證書進行身份確認。CA(Certificate Authority,證書頒發機構)是專門用於認證一個網站合法性的組織。服務商獲得CA證書后,建立安全連接時可以帶上 CA 的簽名。而 CA 的安全性由操作系統或瀏覽器來認證。如果和你建立安全連接的人帶着這些人的簽名,那么認為這個安全連接是安全的,沒有遭到中間人攻擊。
另外在消息的傳遞過程中,每個TLS記錄還會通過MAC(Message Authentication Code, 消息認證碼)來驗證消息的完整性。MAC算法是一個單向加密的散列函數(本質上是一個校驗和),密鑰由連接雙方協商確定。
綜上,HTTPS中的TLS協議通過密鑰協商、身份驗證、消息完整性驗證來保障通信的安全。
三、HTTP/2是如何提高傳輸性能的?
1. 二進制分幀層
HTTP/2 的語義與HTTP/1.x兼容,包括HTTP方法、狀態碼、URI、首部字段等,最大的不同是在應用層和傳輸層之間增加了二進制分幀層。HTTP/2 將所傳輸的信息分割為更小的消息和幀,並對它們采用二進制格式的編碼,將首部封裝到HEADERS幀,將消息體封裝到DATA幀。
2. 並行請求和響應,每個域名一個TCP連接
HTTP/1.1中,在一個TCP連接上可以發送多個HTTP請求和響應,但服務器會依次返回響應結果,也就是說多個響應必須排隊。為了改進性能,瀏覽器對於並發請求支持建立多個TCP連接(chrome里是6個)。但是這樣會增加客戶端和服務器的資源占用,運維成本提高,另外,每個並發的請求都要進行TCP握手,這種方式帶來的性能提升也是有限的。
HTTP/2的二進制分幀層使在一個TCP連接上並行請求和響應的訴求成為現實,客戶端和服務器可以把HTTP消息分解為互不依賴的幀,亂序發送,到另一端再重新組合起來。下圖中,可以看到stream5的請求和steam1、steam3的響應可以同時傳輸。每個流都有對應的ID,由客戶端發起的流的ID均為奇數。
HTTP/2 可以處理並行請求和響應,所有HTTP/2連接都是持久化的,因此不再依賴建立多個TCP連接,服務器和客戶端之間只需要一個連接即可。
3. 請求優先級
HTTP/2 中每個流都可以帶一個優先值,服務器可以根據流的這個優先值,控制資源分配,並在響應數據ready后,優先發送高優先級的幀。但是這里的優先發送並不是絕對的,而是交錯發送不同優先級的數據,否則會造成隊首阻塞的問題。另外,HTTP/2只是提供了賦予流優先級的機制,沒有規定服務器的優先級處理算法。
瀏覽器對根據資源的類型和在頁面中的位置來判斷資源的請求優先級,具體可以的devTool里network里查看每個資源的Priority。Chrome里Priority值分為多種,如Hightest、High、Medium、Low、Lowest等,通過wireshark抓包可以看到,不同Priority在傳輸的幀中對應不同的數值。
4. 服務器推送
在HTTP/1.1中使用內聯CSS、JavaScript,或者使用數據URI嵌入圖片等資源,可以看成是一種服務器推送的形式。在HTTP/2中,允許服務器對一個客戶端請求發送多個響應,比如客戶端請求了一個html,服務器可以通過分析html的內容,通過PUSH_PROMISE幀發出創建流和服務器引用資源的要約,推送CSS、JavaScript等資源。同樣的,HTTP/2 中也沒有規定推送算法,可以根據應用場景選擇合適的策略。可以看到,與HTTP/1.1的內聯資源不同,HTTP/2中的服務器推送的資源可以緩存,也可以由多個頁面共享。
5. 首部壓縮
為了減少首部傳輸的開銷,HTTP/2 采用首部壓縮,在客戶端和服務器端使用“首部表”來跟蹤和存儲之前發送的鍵-值對,對於相同的數據,不再通過每次請求和響應發送,如用戶代理、可接受的媒體類型等。
綜上,可以看到在HTTP/2 中,不再需要域名分區、文件打包、雪碧圖、內聯資源等針對HTTP/1.1的優化方法,而是對應的采用減少域名分區、去掉打包和拼接、利用服務器推送等方式來優化。另一方面,可以發現HTTP/2中,客戶端和應用性能對服務器的依賴更大了,除了服務器的配置,服務器對請求優先級的處理、推送策略都會影響客戶端應用的性能。
參考資料: