HTTP通訊過程包括從客戶端發往伺服器端的請求以及從伺服器端返回客戶端的響應.
1. HTTP報文結構
用於HTTP協議互動的資訊成為HTTP報文. 請求端傳送的HTTP報文成為請求報文,響應端的叫做響應報文. HTTP報文分為報文首部+空行+報文主體,通常並不一定有報文主體.
請求報文首部的結構如下:
- 請求行:包含用於請求的方法,請求URI和HTTP版本。
- 請求首部欄位:客戶端發往服務端請求報文中使用的欄位,用來補充請求的附加資訊、客戶端資訊、對響應呢日用相關的優先順序能內容。
- 通用首部欄位:請求報文和響應報文都會用到的首部。
- 實體首部欄位:包含在請求報文和響應報文中的實體部分所使用的首部,用來補充內容的更新時間和實體相關的資訊。
- 其他:自行擴充套件的。
- 狀態行:包含表明響應結果的狀態碼,原因短語和HTTP版本。
- 響應首部欄位:由伺服器端向客戶端返回響應報文中所使用的欄位,用來補充響應附資訊、伺服器資訊,以及對客戶端的附加要求等資訊。
- 通用首部欄位:請求報文和響應報文都會用到的首部。
- 實體首部欄位:包含在請求報文和響應報文中的實體部分所使用的首部,用來補充內容的更新時間和實體相關的資訊。
- 其他:自行擴充套件的。
2. HTTP編碼
HTTP在傳輸資料時可以按照資料的原貌傳輸, 也可以在傳輸過程中編碼提升傳輸速率. 通過在傳輸時編碼, 能有效地處理大量的訪問請求. 但是編碼是計算機來完成的, 因此會需要消耗更多的CPU等資源.
報文(message):是HTTP通訊的基本單位,由8位組位元組流組成,通過HTTP通訊傳輸. 實體(entity):作為請求和響應的有效載荷資料(補充項)被傳輸,其內容由實體首部和實體主體組成. HTTP報文的主體用於傳輸請求和響應的實體主體. 通常,報文主體等於是實體主體,只有當傳輸中進行編碼操作時,實體主體的內容發生變化,才導致它和報文主體產生差異. 個人理解為實體主體是編碼以後的報文主體.
2.1 壓縮傳輸的內容編碼
HTTP協議中有一種被稱為內容編碼的功能可以實現壓縮內容的效果,內容編碼是在實體內容上的編碼格式,並保持實體資訊原樣壓縮,內容編碼後的實體由客戶端接收並負責解碼.
內容編碼的常見幾種方式:
- gzip (GUN zip)
- compress (UNIX系統的壓縮標準)
- deflate (zlib)
- identity (不進行編碼)
2.2 分割傳送的分塊傳輸編碼
分塊傳輸編碼是將實體主體分割成多個部分(塊), 每一塊都會用十六進位制來標記塊的大小,而實體主體的最後一塊會用"0"來標記.客戶端負責解碼,恢復到編碼前的實體主體.
3. 傳送多種資料格式的多部分物件集合
MIME(Multipurpose Internet Mail Extensions, 多用途因特網郵件擴充套件)機制, 允許郵件處理文字, 圖片, 視訊等各個不同型別的資料. 可以傳送文字,圖片,視屏等不同型別的資料. HTTP協議中也採納了多部分物件集合,傳送的一份報文主體內可以包含多型別實體,通常在圖片或文字上傳時使用.
多部分物件集合 | 作用 |
---|---|
multipart/form-data | 表單檔案上傳時使用 |
multipart/byteranges | 狀態碼206(Partial Content, 部分內容)響應報文包含了多個範圍的內容時使用 |
在HTTP報文中使用多部分物件集合時, 需要在首部欄位中加上Content-type欄位, Content-type欄位說明了實體主體內物件的媒體型別. 使用boundary欄位來劃分多部分物件集合指明的各類實體, 在boundary字串指定的各個實體的起始行之前插入"--"標記做為開始, 在多部分物件集合對應的字串的最後插入"--"標記做為結束. 如上以"--AbB03x"做為開始, 以"--AbB03x--"做為結束.
4. HTTP狀態碼
狀態碼的職責是當客戶端想伺服器端傳送請求時, 描述返回的請求結果. 藉助狀態碼, 使用者可以知道伺服器端是正常的處理了請求還是出現了錯誤.
4.1 2xx成功
200:OK, 請求成功 204:No Content, 服務端接收的請求已經成功處理,但是返回的響應報文中不包含實體的主體部分, 另外也不允許返回任何實體的主體. 206:Partial Content, 客戶端進行了範圍請求,而伺服器成功執行了這部分的GET請求.
4.2 3xx重定向
3xx的響應表明客戶端需要執行某些特殊的處理才能正確請求.
301:Moved Permanently, 永久性重定向, 表示請求的資源已經被分配到了新的URI, 以後請求都是用現在所指的URI. 302:Found, 臨時性重定向, 表示請求的資源已被分配到新的URI, 希望使用者(本次)能使用新的URI訪問.和301狀態類似,但是302狀態碼代表的資源不是被永久移動,只是臨時性質的。 303:See Other,該狀態碼錶示由於請求對應的資源存在著另一個URI,應使用GET方法定向獲取請求的資源。303狀態碼和302狀態碼有著相同的功能,但是303狀態碼錶明客戶端應採用GET方法獲取資源,這點與302狀態碼有區別。 304:Not Modified,改狀態表示客戶端傳送附帶條件的請求時,服務端允許請求訪問資源,但未滿足條件的情況。304狀態碼返回時不包含響應的主體部分。304雖然被劃分在3XX,但是與重定向無關。 307:Temporary Redirect,臨時重定向,與302有相同的含義,但是307不會將POST改為GET。
4.3 4xx客戶端錯誤
4xx的響應結果表明客戶端是傳送錯誤的原因所在.
400:Bad Request, 請求報文中存在語法錯誤. 401:Unauthorized, 請求需要有通過HTTP認證(BASIC認證,DIGEST認證)的資訊. 403:Forbidden, 表明對請求資源的訪問被伺服器拒絕了. 404:Not Found, 表明伺服器上無法找到請求的資源.
4.4 5xx伺服器錯誤
5xx的響應結果表明伺服器本身傳送錯誤.
501:Internal Server Error, 表明伺服器端在執行請求時發生了錯誤. 503:Service Unavailable, 表明伺服器暫時處在超負荷或者正在進行停機維護,現在無法請求.如果事先得知解除以上狀況需要的時間, 最好寫入Retry-After首部欄位返回給客戶端.
5. HTTP首部
HTTP協議的請求和響應報文中必定包含HTTP首部, 我們來看一下HTTP首部的結構以及各欄位的用法.
5.1 HTTP首部結構
請求報文首部:請求行+請求首部欄位+通用首部欄位+實體首部欄位+其他. 請求行包括方法(GET POST), URI, HTTP版本.
響應報文首部:狀態行+響應首部欄位+通用首部欄位+實體首部欄位+其他. 狀態行包括HTTP版本, 狀態碼.
5.2 HTTP首部欄位
HTTP首部欄位是構成HTTP報文的要素之一, 在客戶端和服務端之間以HTTP協議通訊的過程中, 首部欄位起到傳遞額外重要資訊的作用. 首部欄位可以提供報文主體大小, 所使用的語言, 認證資訊等內容.
HTTP首部欄位的結構為首部欄位名: 欄位值
, 指令的引數是可選的, 多個指令之間用","分隔, 例如首部欄位'Cache-Control'的指令用於請求以及響應時:
Cache-Control: private, max-age=0, no-cache
複製程式碼
HTTP首部欄位分為: 通用首部欄位, 請求首部欄位, 響應首部欄位, 實體首部欄位.
5.2.1 通用首部欄位表
通用首部欄位是請求報文和響應報文都會用到的首部.
5.2.2 請求首部欄位
從客戶端傳送請求到服務端使用的首部.補充了請求的附加內容,客戶端資訊,響應內容優先順序等資訊.
5.2.3 響應首部欄位
從服務端向客戶端返回響應報文時使用的首部.補充了相應的附加內容.
5.2.4 實體首部欄位
針對請求報文和響應報文的實體部分使用的首部.
6. 確保安全的HTTPS
HTTP協議中可能存在資訊竊聽或身份偽裝等安全問題, 使用HTTPS通訊機制可以有效地防止這些問題.
6.1 HTTP存在的問題
HTTP協議存在一下不足之處:
- 通訊使用明文, 內容可能被竊聽
- 不驗證通訊方的身份, 因此可能遭遇偽裝
- 無法驗證報文的完整性, 所以有可能已遭篡改
6.1.1 通訊使用明文, 內容可能被竊聽
HTTP本身不具備加密的功能, 無法對通訊整體進行加密, HTTP報文使用明文的方式進行傳輸.
網際網路中都是相通的, 在通訊線路上的某些網路裝置, 光纜, 計算機都可能遭到惡意窺視, 竊取通訊資料, 為了防止資訊被惡意竊聽, 可以使用加密技術.
通訊的加密: 將通訊進行加密, HTTP通過和SSL或TLS的組合使用, 加密HTTP的通訊, 使用SSL建立安全通訊線路之後, 就可以在安全的通訊線路上進行通訊, 與SSL組合使用的HTTP稱為HTTPS.
內容的加密: 將通訊的內容進行加密, 把HTTP報文裡所包含的內容進行加密處理. 這種情況, 客戶端需要將HTTP報文進行加密以後再傳送請求, 這就要求客戶端和服務端具備相同的加密和解密機制.需要注意的是, 經過加密之後的內容還是可以被篡改的. 只對HTTP報文主體進行加密, 不加密報文頭部.6.1.2 不驗證通訊方的身份, 因此可能遭遇偽裝
在HTTP通訊時, HTTP協議中的請求和響應不會對通訊方進行確認, 任何人都可以發起請求, 伺服器接收到請求以後就會返回響應, 這裡就存在安全問題, 客戶端可能是冒充的客戶端, 伺服器可能是冒充的伺服器. 使用SSL可以解決這個問題, SSL不僅提供加密處理, 還使用了一種被稱為證書的手段. 證書是值得信任的第三方機構頒發, 用來證實伺服器和客戶端的身份, 證書偽造在技術上是異常困難的一件事, 所以只要能夠確認通訊方持有的證書, 就可以判斷通訊方的身份.
6.1.3 無法驗證報文的完整性, 所以有可能已遭篡改
HTTP協議無法證明通訊的報文完整性, 不能保證傳送請求以後, 接收到的響應就是對應客戶端的響應, 中間可能被攔截篡改.
6.2 HTTPS
新增了加密和認證機制的HTTP稱為HTTPS.
HTTPS並非一種新協議, 只是在HTTP通訊介面部分用SSL和TLS協議替換, 通常HTTP直接和TCP通訊, 當使用SSL時, HTTP先和SSL通訊, SSL再和TCP通訊, HTTP就擁有了HTTPS的加密, 證書和完整性保護功能.
6.2.1 SSL中的加密
SSL採用一種叫做公開祕鑰加密的加密方式, 加密演算法是公開的, 祕鑰是保密的. 加密和解密都用到祕鑰, 如果祕鑰被其他人竊取, 那麼加密就無意義了.
加密和解密使用同一個祕鑰的方式成為共享金鑰加密, 也成為對稱金鑰加密. 以共享金鑰方式加密時必須將金鑰傳送給對方, 問題來了, 怎麼講共享金鑰安全傳送給對方呢? 如果共享金鑰在傳送的過程中被攔截, 那麼加密還有什麼意義..
為了解決這個問題, 我們來引入公開金鑰的概念, 公開金鑰加密使用一對非對稱的金鑰, 一把是私有金鑰一把是公開祕鑰, 私有金鑰只有自己知道, 公開金鑰可以任意公開. 客戶端和服務端各有一對金鑰, 客戶端傳送請求的時候使用服務端的公開金鑰對內容進行加密, 服務端接收到客戶端的請求, 使用自己的私有金鑰對內容進行解密, 然後使用客戶端的公開金鑰對響應進行加密, 客戶端接收到響應以後使用自己的金鑰對響應進行解密.
HTTPS採用共享金鑰加密和公開金鑰兩者並用的混合加密機制, 公開金鑰加密相比共享金鑰加密, 公開金鑰加密的處理速度相對較慢, 所以我們來考慮共享金鑰的加密處理, 共享金鑰的加密處理的問題在於我們如何將金鑰安全的傳達給對方. 我們可以考慮使用公開金鑰的加密方式將共享金鑰作為內容傳遞給對方, 對方使用自己的金鑰將內容解密以獲取到共享金鑰, 這樣共享金鑰就被安全傳達, 以後的通訊就使用共享金鑰加密的方式進行通訊.
至此, 還有一個問題需要考慮, 我們在使用公開金鑰進行加密時, 如何保證公開金鑰的正確性? 比如我們在和某臺伺服器在公開金鑰加密的方式下通訊時, 如何確保我們收到的公開金鑰就是我們要通訊的那臺伺服器的公開金鑰呢? 很可能在公開金鑰傳輸的過程中, 公開金鑰已經被篡改了. 為了解決這個問題, 我們要讓公開金鑰和我們所說的這臺伺服器最對應, 可以使用由數字證書認證機構(CA, Certificate Authority)和其相關機關頒發的公開金鑰證書.
數字證書認證機構是在客戶端和伺服器都信賴的第三方認證機構的立場上. 伺服器的運營認證人員向數字證書認證機構提出公開金鑰的申請, 數字證書認證機構在確定申請者的身份後對公開金鑰進行簽名, 生成數字證書, 或者叫做證書. 然後分配這個已簽名的公開金鑰. 在通訊的時候, 伺服器會將這個證書傳送給客戶端, 客戶端接收到這個證書, 使用伺服器的公開金鑰對證書進行驗證, 如果驗證通過, 客戶端可以確認伺服器的公開金鑰是值得信賴的, 此處伺服器的公開金鑰必須安全的轉交給客戶端, 如何安全的將公開金鑰轉交是一件很困難的事情, 因此, 很多瀏覽器開發商釋出版本時, 會事先在內部植入常見認證機構的公開金鑰, 那麼上邊我們所說的保證公開金鑰正確性的問題就解決了.
客戶端已經完成了對服務端身份的驗證, 那麼服務端是否可以對客戶端的身份做驗證呢? HTTPS中可以使用客戶端證書, 使用客戶端證書可以對客戶端進行認證, 其作用和伺服器證書類似. 但是這裡存在一個問題, 就是客戶端證書的獲取以及證書的釋出. 由於客戶端證書是收費的, 也就是有多少使用者就要購買多少客戶端證書, 這個在大天朝來說是不太現實的. 而且購買完證書以後, 客戶端需要手動安裝, 這個對不同的使用者來說也是不太容易實現的. 但是對於一些安全性要求很高的業務來說, 客戶端認證還是有必要的, 比如銀行的網上銀行就採用了客戶端證書.
6.2.2 HTTPS通訊過程
這部分的內容理解以後再整理