從 HTTP 瞎逼逼到 HTTP/2

我真的是在瞎逼逼,因?yàn)楣馐?HTTP,就足夠講一塊磚頭了。而且,HTTP 只是協(xié)議棧的應(yīng)用層的其中一個協(xié)議:),不過其他協(xié)議都不在本文討論范圍之內(nèi)。如有疏漏,請指正。

概述:HTTP vs HTTPS vs HTTP/2 vs SSL vs TLS:這些都是啥子跟啥子?

很多縮寫詞被用于描述客戶端與服務(wù)器端交流的過程。這些詞經(jīng)常被不熟悉內(nèi)部原理的人混淆。

HTTP (Hypertext Transfer Protocol) 是客戶端和服務(wù)器端都必須實(shí)現(xiàn)的基本交流協(xié)議。它涉及到請求 (requests),響應(yīng) (responses),會話 (sessions),緩存 (caching),認(rèn)證 (* authentication) 以及更多。在這個協(xié)議以及 HTML (Hypertext Markup Language*) 上的工作,開始于 1989 年,由在 CERN 的 Sir Tim Berners-Lee 和他的團(tuán)隊(duì)主持。這個協(xié)議的第一個官方版本 (HTTP 1.0) 發(fā)布于 1996 年,隨后在 1997 年發(fā)布了現(xiàn)在廣泛使用的版本 (HTTP 1.1)。

這個協(xié)議在瀏覽器和服務(wù)器間傳輸明文 (clear) 信息,允許通過傳輸信息的網(wǎng)絡(luò)查看傳輸?shù)男畔ⅰ_@會產(chǎn)生安全的擔(dān)憂,所以 HTTP Secure (HTTPS) 被引入了。HTTPS 允許客戶端和服務(wù)器端先建立一個加密的通道,然后通過這個通道傳輸明文信息,有效地防止了信息的竊聽。

加密通道是通過 Transport Layer Security (TLS) 協(xié)議創(chuàng)建的,這個協(xié)議以前叫 Secure Socket Layer (SSL)。這兩個術(shù)語經(jīng)?;Q著使用。SSL 3.0 正在被 TLS 1.0 替代。SSL 是 Netscape 開發(fā)的協(xié)議,而 TLS 是一個 IETF 標(biāo)準(zhǔn)。在寫這篇文章的時候,所有版本的 SSL (1.0, 2.0, 3.0) 都由于許多的安全問題而被廢棄,使用它們將會在現(xiàn)代瀏覽器中產(chǎn)生警告,TLS 版本 (1.0, 1.1, 1.2) 正在使用中,1.3 版本現(xiàn)在還是草案。

所以,在大約 1996 或 1997 的某個時間,我們有了互聯(lián)網(wǎng)的當(dāng)前穩(wěn)定版本 (有或者沒有 SSL/TLS 的 HTTP 1.1),這個 HTTP 版本仍然驅(qū)動著現(xiàn)在絕大多數(shù)網(wǎng)站。以前,HTTP 用于非敏感通信,比如閱讀新聞,而 HTTPS 用于敏感通信,比如認(rèn)證和電子商務(wù)。然而,對隱私權(quán)的關(guān)注不斷增加,一些瀏覽器如 Google Chrome 現(xiàn)在會標(biāo)記 HTTP 網(wǎng)站 為 “not private”,將在未來針對 HTTP 引入警告。

HTTP 協(xié)議的下一代升級版 —— HTTP/2,于 2015 年發(fā)布,正在被越來越多的網(wǎng)站所采納。這個協(xié)議增加了新的特色,如 壓縮 (compression),多路復(fù)用 (multiplexing),請求優(yōu)先級 (prioritization of requests)等,用于減少等待時間、提升性能和安全性。

在 HTTP 1.1 版本,安全連接是可選的,你可以使用 HTTP 或 HTTPS,但在 HTTP/2,安全連接幾乎是強(qiáng)制的,即使標(biāo)準(zhǔn)定義了有 TLS 的 HTTP/2 和沒有 TLS 的 HTTP/2,但大部分瀏覽器提供商已經(jīng)聲明它們將只支持擁有 TLS 的 HTTP/2。

HTTP

HTTP 的基本性質(zhì)

簡單

HTTP 的消息被設(shè)計(jì)為簡單可讀。這一點(diǎn)只要你打開瀏覽器控制臺看看請求和響應(yīng)頭就知道了。

可擴(kuò)展

除了規(guī)范規(guī)定的那些 header,我們會看到很多非官方規(guī)定的 header,這些擴(kuò)展的 header 可以用來實(shí)現(xiàn)新的功能。

無狀態(tài)

這意味著即使你對服務(wù)器發(fā)起過一次請求,當(dāng)你再發(fā)起一次請求時,服務(wù)器也不知道你拜訪過它,基本的 HTTP 請求中是不含狀態(tài)信息的。所幸我們可以增加 cookie 的頭部擴(kuò)展來記錄狀態(tài)信息。

使用可靠連接

HTTP 依賴于運(yùn)輸層的 TCP 協(xié)議進(jìn)行消息傳遞,而 TCP 是可靠的。

狀態(tài)碼

狀態(tài)碼的第一個數(shù)字代表當(dāng)前響應(yīng)類型

  • 1xx - 信息,請求已被服務(wù)器接收,繼續(xù)處理
  • 2xx - 成功,請求已成功被服務(wù)器接收、理解、并接受
  • 3xx - 重定向,需要后續(xù)操作才能完成這一請求
  • 4xx - 客戶端錯誤,請求含有詞法錯誤或者無法被執(zhí)行
  • 5xx - 服務(wù)器端錯誤,服務(wù)器在處理某個正確請求時發(fā)生錯誤

HTTP 的請求方法

較少用的方法

  • OPTIONS:請求服務(wù)器告知其支持的各種功能??梢栽儐柗?wù)器通常支持哪些方法,或者對某些特殊資源支持哪些方法
  • HEAD:向服務(wù)器發(fā)出指定資源的請求,但服務(wù)器在響應(yīng)中只返回首部,不會返回實(shí)體的主體即資源的 body 部分
  • PUT:向服務(wù)器寫入資源
  • DELETE:請服務(wù)器刪除請求 URL 所指定的資源
  • TRACE:HTTP 請求在傳輸?shù)倪^程中是可能會被修改的。這個方法允許客戶端在最終將請求發(fā)送給服務(wù)器時,看看它變成了什么樣子。主要用于測試或診斷
  • CONNECT:這個方法將請求的連接轉(zhuǎn)換為透明的 TCP/IP 隧道,通常用于加快基于 SSL 加密的通信
  • PATCH:這個方法請求對資源進(jìn)行局部修改

常用方法

GET && POST

GET 是最常用的方法,用于請求服務(wù)器發(fā)送某個資源。POST 方法用于向服務(wù)器發(fā)送數(shù)據(jù),注意這和 PUT 的寫入資源是不同的,寫入的資源是存儲在服務(wù)器的,而發(fā)送的數(shù)據(jù)會發(fā)送到其他地方去處理,這可能會導(dǎo)致新資源的創(chuàng)建或已存在資源的更新,POST 通常用于支持 HTML 表單。

這兩個方法有什么區(qū)別?

冪等
在數(shù)學(xué)中,冪等有兩種主要含義:

  • 在某二元運(yùn)算下,冪等元素是指被自己重復(fù)運(yùn)算的結(jié)果等于它自己的元素。例如 0 * 0 仍然為 0,所以 0 在乘法下是冪等的。
  • 某一元運(yùn)算為冪等的時,其作用在任一元素兩次后會和其作用一次的結(jié)果相同,例如 恒等函數(shù) f(x) = x 就是冪等的。

在計(jì)算機(jī)網(wǎng)絡(luò)中,假如在不考慮諸如錯誤或者過期等問題的情況下,若干次請求的副作用與單次請求相同或者根本沒有副作用,那么這些請求方法就能夠被視作是“冪等”的。

我們知道,GET 用于表單數(shù)據(jù)提交時,表單數(shù)據(jù)會被編碼在請求的 URI 上,這樣極不安全,因?yàn)檎埱蟮牡刂房赡茉谇槿さ竭_(dá)目的地之前被打印,然后被第三方看到。而 POST 提交的數(shù)據(jù)是放在請求體中的,比 GET 提交數(shù)據(jù)安全,當(dāng)然,沒有 HTTPS,POST 提交的數(shù)據(jù)也能被看到。

但是最主要的區(qū)別,應(yīng)該為如下三點(diǎn):

  • 安全性(safe): GET 請求是安全的,這里的安全是指 GET 方法只獲取信息而不做其他操作。而 POST 請求則是不安全的,因?yàn)樗鼤禄騽?chuàng)建資源。

  • 冪等性(idempotent): GET 請求是冪等的,冪等就是上面所說的若干次請求的副作用與單次請求相同,而 POST 請求則是不冪等的。

  • 可緩存性(cacheable): GET 請求的響應(yīng)是可緩存的,POST 請求的響應(yīng)一般是不可緩存的,除非設(shè)置了合適的 Cache-Control 或 Expires 頭部字段。

HTTPS

為什么優(yōu)先要使用 HTTPS?

有三個主要原因:

  • 機(jī)密性 (Confidentiality)

這能保護(hù)通信的雙方在公共媒介中免遭信息竊聽。如果沒有 HTTPS,當(dāng)你通過 WiFi 接入點(diǎn)網(wǎng)上購物時,WiFi 接入點(diǎn)的運(yùn)營者就能看到你的信用卡之類的隱私信息。

  • 數(shù)據(jù)完整性 (Integrity)

這能保證信息能不受改變地完整到達(dá)目的地。比如,WiFi 可以在我們的網(wǎng)站上增加廣告,降低圖片質(zhì)量或者改變文章的內(nèi)容。HTTPS 能確保網(wǎng)站不被更改。

  • 身份驗(yàn)證 (Authentication)

這能保證網(wǎng)站不會是假冒的,域名是哪個,站點(diǎn)就是哪個。比如,一些運(yùn)行 WiFi 接入點(diǎn)的猥瑣之人可以把瀏覽器導(dǎo)向一些假冒的網(wǎng)站。HTTPS 能確保example.com就是真的example.com,有些安全證書甚至要檢查網(wǎng)站的合法身份,讓你知道yourbank.comYourBank, Inc,即 YourBank 公司。

使用 HTTP 頭部字段保護(hù)你的 web 應(yīng)用

禁用秘密信息的緩存

瀏覽器默認(rèn)緩存 HTTP 的 GET 請求的響應(yīng),如果使用的是共享個人電腦 (網(wǎng)吧不就是么?),那么猥瑣之人就能通過訪問瀏覽器的緩存得到他人的隱私信息。所以我們要在返回隱私信息時使用三個響應(yīng)頭字段來禁用客戶端的緩存:

  • Cache-Control: no-cache, no-store, max-age=0, must-revalidate
    cache-control 字段用來指定在這次的請求/響應(yīng)鏈中的所有緩存機(jī)制都必須遵守的指令。上面的三個指令告訴客戶端和代理在使用緩存前必須送請求到服務(wù)器進(jìn)行驗(yàn)證,不要儲存響應(yīng),在請求發(fā)生之后的 0 秒后緩存即過期,在使用緩存的響應(yīng)前檢查其狀態(tài)并禁止使用過期的響應(yīng)。

  • Pragma: no-cache
    這個字段用于向后兼容 HTTP 1.0,確保老客戶端能不緩存響應(yīng)。

  • Expires: -1
    這個字段用于指定響應(yīng)過期的時間戳。指定為-1的話,客戶端就會立即把響應(yīng)當(dāng)做過期的,這就避免了緩存。

請?jiān)谛枰Wo(hù)隱私時才禁用緩存,否則你的應(yīng)用加載速度將大打折扣。

強(qiáng)制 HTTPS

HTTPS 的重要性我在前面已經(jīng)說了,要強(qiáng)制 HTTPS,我們要使用 HTTP Strict Transport Security (HSTS) 頭部字段,具體可以設(shè)置為Strict-Transport-Security: max-age=31536000; includeSubDomains; preload。

max-age是指示瀏覽器為當(dāng)前域名緩存這個頭部字段指定秒數(shù),這里是緩存一年。includeSubDomains指示瀏覽器將 HSTS 應(yīng)用于當(dāng)前域名的所有子域名。preload強(qiáng)制瀏覽器總是安全地加載你的 web 應(yīng)用,甚至在你第一次訪問網(wǎng)站且未收到響應(yīng)前,這個特性是通過將一個安全預(yù)加載的域名的列表硬編碼到瀏覽器代碼中實(shí)現(xiàn)的,要使用這個特性你需要在 HSTS Preload List Submission 注冊你的域名,當(dāng)然啦,使用這個指令你得確保你的應(yīng)用能只使用 HTTPS。

允許 XSS 過濾

XSS 即跨站腳本攻擊,是很普遍也很簡單的網(wǎng)絡(luò)攻擊手法。我們會使用X-XSS-Protection: 1; mode=block,X-XSS-Protection這個字段指示瀏覽器是否為當(dāng)前頁面開啟瀏覽器內(nèi)建的 XSS 過濾機(jī)制并覆蓋瀏覽器本身的相關(guān)設(shè)置。1表示允許過濾器,反之為0mode=block指示瀏覽器在檢測到 XSS 攻擊后禁止加載整個頁面。

控制 Framing

一個 iframe 是一個可以允許在一個父 web 應(yīng)用中嵌套一個 web 應(yīng)用的 DOM 元素。這個元素可以讓點(diǎn)擊劫持 (* clickjacking) 更容易。點(diǎn)擊劫持可以欺騙用戶點(diǎn)擊非用戶本意的東西。為了阻止這種攻擊,我們使用X-Frame-Options: SAMEORIGIN,X-Frame-Options*這個字段指示瀏覽器是否允許你的 web 應(yīng)用嵌套在另一個 web 應(yīng)用中,SAMEORIGIN 表示你的應(yīng)用可以在同域名頁面的 frame 中展示。注意當(dāng)在 Content-Security-Policy 字段中指定了 frame-ancestors 時,則 X-Frame-Options 被忽略,見 這里。

明確白名單

CSP (Content Security Policy) 定義了一個非常強(qiáng)大的基于瀏覽器的安全機(jī)制,允許對你的 web 應(yīng)用中的資源加載和腳本執(zhí)行加以控制。有了它,你可以將允許腳本加載、ajax 調(diào)用、圖片和樣式表加載的域列入白名單,可以允許或禁止內(nèi)聯(lián)腳本和動態(tài)腳本等。我們可以通過簡單設(shè)置Content-Security-Policy: script-src 'self'來允許同源的腳本加載以及阻止動態(tài)腳本和內(nèi)聯(lián)腳本執(zhí)行。Content-Security-Policy 是個比較復(fù)雜的頭部字段,詳細(xì)的配置可以在這里看到。

阻止 Content-Type 嗅探

為了使用戶體驗(yàn)更連貫,很多瀏覽器實(shí)現(xiàn)了一個叫 “Content-Type 嗅探” 或 “MIME 嗅探” 的功能,這個功能使瀏覽器能通過實(shí)際資源的比特位檢測 HTTP 中響應(yīng)資源的類型而不理會響應(yīng)頭中的Content-Type字段聲明的資源類型。但這會導(dǎo)致 MIME 混淆攻擊 (MIME confusion attack)。于是乎,我們要使用X-Content-Type-Options: nosniff,指示瀏覽器在處理獲取的資源時不要使用嗅探。

HTTP/2

多數(shù)主流瀏覽器已經(jīng)在2015年底支持了該協(xié)議。此外,根據(jù) W3Techs 的數(shù)據(jù),在2017年5月,在排名前一千萬的網(wǎng)站中,有13.7% 支持了HTTP/2。這真真是極吼滴!有圖有真相。

http2 support

HTTP/2 相比 HTTP 1.x 的主要區(qū)別

是二進(jìn)制的而非文本的

有別于 HTTP/1.1 中的明文請求,HTTP/2 將一個 TCP 連接分為若干個流 (stream),每個流中可以傳輸若干消息 (message),每個消息由若干最小的二進(jìn)制幀 (frame) 組成。這樣更利于高效地解析,而且不容易出錯,畢竟 HTTP/1.x 的 header 中有空白行、大小寫、換行、空行之類的規(guī)定。

是完全多路復(fù)用而非按順序和阻塞的

HTTP/1.x 有一個 head-of-line blocking 的問題,它會讓一個連接一次只能發(fā)送一個請求。多路復(fù)用允許多個請求和響應(yīng)消息同時發(fā)出,甚至可以混合一個消息的一部分和另一個消息。

只開一個連接用于并發(fā)的請求

HTTP/1.x 中為了加載資源會同時打開多個 TCP 連接,每個連接在響應(yīng)時又都會發(fā)送大量數(shù)據(jù),存在中間網(wǎng)絡(luò) (intervening network) 緩沖區(qū)溢出的危險(xiǎn),導(dǎo)致網(wǎng)絡(luò)阻塞和重發(fā) (* retransmits*)。而且,使用那么多的 TCP 連接也是一種大量占用網(wǎng)絡(luò)資源的行為。

壓縮頭部

在大型網(wǎng)站中,一個頁面往往要請求大量資源并得到相應(yīng),算上那些往返的話,那么頭部就會占據(jù)相當(dāng)大的開銷,所以壓縮頭部的好處便變得顯而易見了。

允許服務(wù)器主動推送資源給客戶端

在 HTTP/1.x 中,當(dāng)瀏覽器請求了一個頁面,服務(wù)器發(fā)送了 HTML 頁面的響應(yīng),然后服務(wù)器需要等待瀏覽器解析了 HTML 文件后再發(fā)起嵌入在 HTML 頁面中的多個資源的請求,想想都覺得慢。而服務(wù)器端推送避免了這種往返的延遲,服務(wù)器會主動推送它認(rèn)為的客戶端會需要緩存的資源。要小心的是,這個功能濫用的話,會損害性能。

如何擁抱 HTTP/2?

HTTP/2 是向后兼容 HTTP/1.1 的,所以完全不需要擔(dān)心現(xiàn)有的網(wǎng)站會發(fā)生什么問題。然而,很多對于 HTTP/1.1 來說是最佳實(shí)踐的技巧卻會在使用 HTTP/2 時降低性能。再者,從 HTTP/1.1 轉(zhuǎn)向 HTTP/2 勢必是漫長的,因?yàn)榉?wù)器端升級容易,但只要一日絕大多數(shù)人仍然使用著老舊甚至是史前瀏覽器,客戶端就會是扎心窩的痛。我們需要做些過渡時期的事。

轉(zhuǎn)向 TLS

第一要務(wù)是讓你的網(wǎng)站運(yùn)行在安全連接上,因?yàn)閺S商大佬們已經(jīng)說過了:我們哥們幾個只支持有 TLS 的 HTTP/2,那些不支持 TLS 的可以歇菜了。所以國內(nèi)大片的 HTTP 網(wǎng)站們要好好考慮轉(zhuǎn)向 HTTPS 的事了。

雪碧圖不再總是最佳的選擇

在 HTTP/1.1 中,對于瀏覽器來說,獲取一個巨大的圖片文件比請求多個小圖片文件高效,這是因?yàn)槎鄠€請求會互相排隊(duì),增加加載時間。通常的做法是把多個小圖片轉(zhuǎn)成一個雪碧圖。

轉(zhuǎn)成一個雪碧圖就只需要一個 HTTP 請求了。但是咧,如果一個頁面中只使用到雪碧圖中的一個圖標(biāo),仍然下載整個雪碧圖就顯得不是很好了。HTTP/2 擁有多路復(fù)用的能力,所以多個請求排隊(duì)的事已經(jīng)不存在了,很多時候單個地請求圖片將是更好的選擇。當(dāng)然,需要使用所有圖標(biāo)時,雪碧圖仍然是需要的。

使用 Data URI 內(nèi)嵌圖片是一種阻礙

在 HTTP/1.1 中,為了減少 HTTP 請求,你可以把圖片直接以 Data URI 的形式嵌入 CSS 或 HTML 文件中。因?yàn)檗D(zhuǎn)成的字符編碼會很長,自然增加了 CSS 或 HTML 文件的大小。在 HTTP/2 中,HTTP 請求變得廉價,這種 “最佳實(shí)踐” 便變成了一種妨礙。

合并 CSS 文件和 JavaScript 文件未必好

我們在應(yīng)用的構(gòu)建階段,通常會合并那些小的 CSS 和 JavaScript 文件,本意是減少 HTTP 請求。但是在 HTTP/2 中,HTTP 請求是廉價的,合并便不再顯得有優(yōu)勢。可能更糟糕的是,如果你因?yàn)楹喜⒁肓撕芏喾潜卷撁嫠璧奈募?,反而拖慢了加載速度,當(dāng)然,你是可以通過 webpack 來配置相應(yīng)頁面所需的相應(yīng)文件的,可是別忘了,合并文件是要引入大量處理合并的代碼的,在 HTTP/2 廉價的請求中,這些多余的處理代碼看來有點(diǎn)多余,止增笑耳。

域名分片可能會坑你

在 HTTP/1.1 中,每個域名能打開的連接是受到限制的,大概為 6 - 8 個,具體取決于瀏覽器實(shí)現(xiàn)。如果你實(shí)在要加載大量資源,其中一個方法就是從多個域名中獲取資源,這就是域名分片 (domain sharding)。這個方法能實(shí)現(xiàn)更好的加載時間,也有能導(dǎo)致問題,當(dāng)然,準(zhǔn)備這種服務(wù)就會有額外的開支。HTTP/2 則移除了域名分片的需求,在 HTTP/2 下,瀏覽器只為每個域名打開一個連接,但是人家有多路復(fù)用嘛,并發(fā)請求的數(shù)量根本不受限制 (當(dāng)然也可以通過 SETTINGS_MAX_CONCURRENT_STREAMS 來限制)。而且,域名分片在 HTTP/2 中還會損害性能,因?yàn)樗鼊?chuàng)建了額外的 TCP 連接,妨礙 HTTP/2 為資源進(jìn)行優(yōu)先級排序。

當(dāng)前對于 HTTP/1.1 的最佳實(shí)踐是限制域名分片為 2 個域名。好消息是為了減少工作并在 HTTP/1.1 和 HTTP/2 都能達(dá)到很好的效果,有方法可以讓 HTTP/2 合并你的連接,具體方法見 Google 家的 slide 26。

實(shí)現(xiàn)

可喜的是,現(xiàn)在已經(jīng)有大量的 HTTP/2 的服務(wù)器端實(shí)現(xiàn)了,涵蓋了多種語言,參見
Implementations。

Reference

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 一、概念(載錄于:http://www.cnblogs.com/EricaMIN1987_IT/p/3837436...
    yuantao123434閱讀 8,724評論 6 152
  • Http協(xié)議詳解 標(biāo)簽(空格分隔): Linux 聲明:本片文章非原創(chuàng),內(nèi)容來源于博客園作者M(jìn)IN飛翔的HTTP協(xié)...
    Sivin閱讀 5,333評論 3 82
  • 1. 網(wǎng)絡(luò)基礎(chǔ)TCP/IP HTTP基于TCP/IP協(xié)議族,HTTP屬于它內(nèi)部的一個子集。 把互聯(lián)網(wǎng)相關(guān)聯(lián)的協(xié)議集...
    yozosann閱讀 3,598評論 0 20
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,502評論 19 139
  • 大家都知道網(wǎng)絡(luò)營銷是越來越重要,然而競爭越來越大,運(yùn)營成本越來越高,內(nèi)容營銷好像也越來越不管用,然而內(nèi)容營銷又越來...
    企邦在線閱讀 623評論 0 0

友情鏈接更多精彩內(nèi)容