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