本篇文章將介紹應用層中使用最為廣泛的協議,即HTTP協議,譯名叫做超文本傳輸協議,也有叫超文本轉移協議的,本文的重點內容是介紹如何進行HTTP抓包,HTTP協議的格式是怎樣的,常見的字段與狀態碼以及對Cookie的理解。
1.HTTP概述
1.1什么是HTTP
HTTP/HTTPS是一種應用層的協議,應用層協議很多時候都是程序員自己定制的,需要根據具體的場景來制定應用層協議,但是由于程序員水平參差不齊,大佬設計的協議很好用,菜鳥設計的協議一言難盡,于是有一些大佬就發明了很好用的協議,直接讓大家照搬,HTTP就是其中的一個典型代表,HTTP雖然已經設計好了,但是它的擴展性極強,可以根據需要讓程序員自定義數據信息。
HTTP是一種超文本傳輸協議,是互聯網上應用最為廣泛的一種網絡協議。那如何才能看到HTTP的報文格式或信息,這就需要對HTTP進行抓包,下面介紹一下如何進行HTTP的抓包。
1.2抓包工具Fidder的使用
Fidder是一款專門抓HTTP/HTTPS包的軟件,它的原理就是充當一個代理,比如當訪問一個網站時,會先將請求發送給Fidder,然后Fidder再把請求發送給目標網頁的服務器,同理服務器返回的響應也一樣,先需要經過Fidder,再發送給客戶端。
這樣,Fidder就能夠捕獲到HTTP的請求與響應,由于Fidder充當的是一個“代理”的角色,所以使用Fiddder時不能夠有其他使用或修改代理的軟件運行,否則Fidder就不能夠捕獲到HTTP/HTTPS的包。

1.2.1下載
下載很簡單,直接去官網下載即可,網址為www.telerik.com/fiddler。
首先直接打開網頁是下面這個樣子的。

進入官網后,我們往下翻,找到如圖的頁面,Fidder Classic,這個是免費的。

點擊Try to Free。

點擊后,會跳轉到如下的頁面。

填寫信息,下載即可。
1.2.2安裝
至于安裝,就非常簡單了,一路next就可以了。
安裝過后,需要設置一下,首先現在的大部分網頁都是HTTPS格式的,所以需要設置HTTPS的捕捉。
第一步,找到Tools選項,選擇Options,找到HTTPS。

將如圖的選項全部勾上,并確定。

然后,會有一個窗口跳出來,一定要點yes,不然就要重裝Fidder了,這樣Fidder就可以使用了。
如果Fidder一直報The system proxy was changed,click to reenable fiddler capture,這樣的警告,這種情況大概率是存在沖突的軟件,代理被修改了,參考一位大佬的博客可以解決:blog.csdn.NET/legend818/a…
1.2.3如何使用
Fidder左側是捕獲到的HTTP(s)包,雙擊某個包后,會在右側顯示詳細信息。


顯示詳細信息后,使用Raw模式可以看到http的本體。

點擊View in Notepad可以使用記事本打開,查看詳情。

對于右側的上下兩欄,上面是請求,下面是對應的響應。
我們發現響應里面的內容有一串亂碼,這可能是壓縮或者加密了,可以點擊下面黃色的按鈕來顯示服務器的響應結果。

點擊之后:

Fidder的基本使用差不多就是這些。
1.3URI與URL
URI即網絡資源標識符,URL即網絡資源定位符,前者是使用唯一字符串來標識互聯網中某一資源,后者使用字符串來表示某個資源的位置,URL可以理解為URI的一種實現,就像接口與實現類的關系一樣。
URL(I)格式:

協議方案名:必選項,使用 http 或https等協議方案名獲取訪問資源時要指定協議類型。不區分字母大小寫,最后附一個冒號:,使用//與后面的字段分隔。 也可使用 jdbc:MySQL:// 或 JAVAscript: //這類jdbc程序或腳本程序的方案名。
登錄信息:可選項,這是上古時期上網的時候,在這里會體現出賬號與密碼,現在基本上沒有了,使用@符號與后面的字段分隔。
服務器地址:必選項,可以使用域名和IP地址來表示,使用:與端口號分隔,沒有端口號:省略。
端口號:可選項,表示訪問主機上哪一個應用程序,該字段為空,瀏覽器會分配默認的端口號,http是80,https是443。
文件路徑:必選項,描述訪問服務器的資源是什么,最簡單的路徑就是一個/,你訪問很多網站的首頁的時候,最后都會有一個/,使用?與查詢字符串分隔。
查詢字符串:可選項,表示瀏覽器或者客戶端傳給服務器自定義的信息,對獲取的資源提出進一步的要求,一般是程序員自定義,所以如果不是你自己寫的,大概率看不懂,使用#與片段標識符分隔。
片段標識符:可選項,表示訪問頁面的子位置,能夠控制瀏覽器滾動到某一位置。
HTTP 協議使用 URI 定位互聯網上的資源。正是因為 URI 的特定功能,在互聯網上任意位置的資源都能訪問到。

1.4URL encode/decode
如果查詢字符串(query string)的內容包含一些具有特定含義的字符需要進行轉義,如/,?,&等,如果含有這些字符,會將這些字符替換為%字符的ASCII碼,這個過程就是encode,反過來將這些轉義的字符串解析為原來的字符,這個過程就是decode。
比如,你在瀏覽器上搜索C++,在URL上就會得到C%2B%2B這樣的字符串。

2.HTTP協議格式
2.1HTTP請求格式
2.1.1基本格式

http請求格式包括請求行,請求報頭和請求正文,報頭與正文之間使用空行做標記進行分隔。 例如,下面的一大段http請求報文。

請求行由三部分構成,分別是方法, URL, HTTP版本號。 方法用來描述請求的目的是什么,比如get方法一般用來獲取服務器的資源。 URL表示想要訪問的網絡資源的位置。 常見HTTP版本號有HTTP/1.0,HTTP/1.1,HTTP/2.0這些都是基于TCP,最新版本的HTTP/3.0是基于UDP。
請求頭部,包含很多行,有許多的鍵值對組成,鍵和值之間使用:來進行分割,至于鍵值對的數量,是不固定的。
請求正文是可選項,不一定會有,像上面的那個例子請求正文就是空的。

2.1.2方法
請求行里面的方法完整地說應該叫做告知服務器意圖的 HTTP 方法,這里的方法與java里面的方法不同,引入這些方法的初衷就是為了表示不同的語義,比如GET表示獲取資源,POST表示上傳資源,但是大多數人寫代碼就是GET/POST一把梭,基本上就沒有考慮各種方法的語義。
在http/1.1版本中,最常使用的方法有GET,POST,還有其他方法,引謝靈運的話來說,GET占八斗,POST占一斗,其他方法分剩下的一斗。
各方法功能如下:

GET :獲取資源 GET 方法用來請求訪問已被 URL 識別的資源。指定的資源經服務器端解析后返回響應內容。也就是說,如果請求的資源是文本,那就保持原樣返回;如果是像 CGI(CommonGateway Interface,通用網關接口)那樣的程序,則返回經過執行后的輸出結果。

POST:傳輸實體主體 雖然用 GET 方法也可以傳輸實體的主體,但一般不用 GET 方法進行傳輸,而是用 POST方法。雖說 POST 的功能與 GET 很相似,但 POST 的主要目的并不是獲取響應的主體內容。

PUT:傳輸文件 PUT 方法用來傳輸文件。就像 FTP 協議的文件上傳一樣,要求在請求報文的主體中包含文 件內容,然后保存到請求 URI 指定的位置。 該方法在HTTP/1.1無驗證機制,不安全,配合驗證機制可以開放使用該方法。

HEAD:獲得報文首部 與GET的區別就是HEAD只返回報文的首部。

DELETE:刪除文件 DELETE 方法按請求 URI 刪除指定的資源,不安全,需配合驗證機制使用。

OPTIONS:詢問支持的方法 詢問服務器支持哪些方法。

TRACE:追蹤路徑 TRACE 方法是讓 Web 服務器端將之前的請求通信環回給客戶端的方法,不常用。

CONNECT:要求用隧道協議連接代理 CONNECT 方法要求在與代理服務器通信時建立隧道,實現用隧道協議進行 TCP 通信。主要使用 SSL(Secure Sockets Layer,安全套接層)和 TLS(Transport Layer Security,傳輸層安全)協議把通信內容加 密后經網絡隧道傳輸。
格式與其他的方法不同:
CONNECT 代理服務器名:端口號 HTTP版本

GET方法可以代替POST方法的使用,POST方法也可以替代GET方法的使用,那GET與POST有什么區別?
答:GET與POST沒有本質區別,但存在細節差別。 從語義上來說,GET一般用來獲取資源,POST一般用來上傳資源,不是強制要求,只是建議。 從習慣上說,通常情況下,GET沒有body(請求正文),GET通過query string(查詢字符串)傳輸數據。通常情況下,POST有body,POST通過body來傳輸數據,這也不是絕對的,只是一種習慣。 其他方面,GET請求一般是冪等的,POST請求一般不冪等,冪等的意思是,你每次輸入相同的請求得到的輸出的結果是確定的,反之不冪等就是輸出的結果是不確定的,因為相同結果得到的輸出結果相同,那么這個結果是可以被緩存的,否則就不能被緩存,也就是說GET可以緩存,POST不可以緩存,能不能緩存是與冪等是有關系的。
2.2HTTP響應格式
2.2.1基本格式

HTTP響應格式包括響應行,響應頭部,響應正文,頭部與正文之間使用空行進行分割。
例如下面的這一段響應報文。

響應行包括協議版本,狀態碼,狀態碼描述三部分組成。
狀態碼表示響應的狀態是怎么樣的,200表示成功,400,500表示失敗,狀態碼描述就是說明對應狀態碼的意思是什么。
響應頭部,分隔符,響應正文在格式上與請求是一樣的,其中響應正文最常見的格式就是html。

2.2.2狀態碼
狀態碼的職責是當客戶端向服務器端發送請求時,描述返回的請求結果。借助狀態碼,用戶可以知道服務器端是正常處理了請求,還是出現了錯誤。

狀態碼的大類類別:

狀態碼個大類下的細分表:
狀態碼與狀態信息 |
該狀態下的情況 |
200 OK |
表示從客戶端發來的請求在服務器端被正常處理了。 ![]()
|
204 No Content |
該狀態碼代表服務器接收的請求已成功處理,但在返回的響應報文中不含實體的主體部分。另外,也不允許返回任何實體的主體。 ![]()
|
206 Partial Content |
該狀態碼表示客戶端進行了范圍請求,而服務器成功執行了這部分的 GET 請求。響應報文中包含由 Content-Range 指定范圍的實體內容。 ![]()
|
301 Moved Permanently |
永久性重定向。該狀態碼表示請求的資源已被分配了新的 URI,以后應使用資源現在所指的 URI。 ![]()
|
302 Found |
臨時性重定向。該狀態碼表示請求的資源已被分配了新的 URI,希望用戶(本次)能使用新的 URI 訪問。 ![]()
|
303 See Other |
該狀態碼表示由于請求對應的資源存在著另一個 URI,應使用 GET方法定向獲取請求的資源。 ![]()
|
304 Not Modified |
該狀態碼表示客戶端發送附帶條件的請求時,服務器端允許請求訪問資源,但沒有滿足請求條件的資源的情況。 ![]()
|
307 Temporary Redirect |
臨時重定向。該狀態碼與 302 Found 有著相同的含義。盡管 302 標準禁止 POST 變換成 GET,但實際使用時大家并不遵守。307 會遵照瀏覽器標準,不會從 POST 變成 GET。但是,對于處理響應時的行為,每種瀏覽器有可能出現不同的情況。 |
400 Bad Request |
該狀態碼表示請求報文中存在語法錯誤。 ![]()
|
401 Unauthorized |
該狀態碼表示發送的請求需要有通過 HTTP 認證(BASIC 認證、DIGEST 認證)的認證信息。另外若之前已進行過 1 次請求,則表示用戶認證失敗。返回含有 401 的響應必須包含一個適用于被請求資源的 WWW-Authenticate 首部用以質詢(challenge)用戶信息。當瀏覽器初次接收到 401 響應,會彈出認證用的對話窗口。 ![]()
|
403 Forbidden |
該狀態碼表明對請求資源的訪問被服務器拒絕了。 ![]()
|
404 Not Found |
該狀態碼表明服務器上無法找到請求的資源。除此之外,也可以在服務器端拒絕請求且不想說明理由時使用。 ![]()
|
500 Internal Server Error |
該狀態碼表明服務器端在執行請求時發生了錯誤。也有可能是 Web應用存在的 bug 或某些臨時的故障。 ![]()
|
503 Service Unavailable |
該狀態碼表明服務器暫時處于超負載或正在進行停機維護,現在無法處理請求。 ![]()
|
418 I'm a teapot |
這個是http的一個彩蛋,增加樂趣,其實沒什么用 |
2.3首部字段
2.3.1分類
HTTP 首部字段根據實際用途被分為以下 4 種類型。
- 通用首部字段(General Header Fields)請求報文和響應報文兩方都會使用的首部。
- 請求首部字段(Request Header Fields)從客戶端向服務器端發送請求報文時使用的首部。補充了請求的附加內容、客戶端信息、響應內容相關優先級等信息。
- 響應首部字段(Response Header Fields)從服務器端向客戶端返回響應報文時使用的首部。補充了響應的附加內容,也會要求客戶端附加額外的內容信息。
- 實體首部字段(Entity Header Fields)針對請求報文和響應報文的實體(正文)部分使用的首部,補充了資源內容更新時間等與實體有關的信息。
2.3.2實體首部字段

常用的幾個字段: Content-Length,計算body部分的長度,可以配合分隔符解決粘包問題。 Content-Type,表示body中的數據格式。
2.3.3請求首部字段

常用字段: User-Agent,表示客戶端是使用什么來進行上網,操作系統信息+瀏覽器信息。
User-Agent: Mozilla/5.0 (windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36
復制代碼
Referer,表示當前的頁面是從哪一個頁面跳轉過來的,但是不一定有,如直接輸入網址,那就沒有原來的那個跳轉頁面。
2.3.4響應首部字段

2.3.5通用首部字段

2.3.6Cookie
因為HTTP是一種無狀態的協議,它無法對之前的發生過的請求和響應狀態進行記憶,如果遇到需要登錄的頁面,登錄之后,再刷新,是需要重新進行登錄的,這個就非常的難受,為了解決這個問題,引入了Cookie機制。

但是也有好處,可以減少服務器的 CPU 及內存資源的消耗。
Cookie是瀏覽器為頁面提供的一種持久化儲存數據的機制,即就是將數據存儲磁盤上,不會因為瀏覽器或者電腦重啟而導致數據丟失。
Cookie會按照域名來進行分類并組織,針對每一個域名,都會分配一個“小房間”(一塊獨立的儲存空間),這些小房間之間是相互獨立的,在每個“小房間”里面會按照鍵值對的方式儲存數據(值),每個鍵值對之間使用&來進行分隔。
那Cookie的數據從哪里來?其實是從服務器返回給客戶端的,服務器完成客戶端的身份認證之后會通過的頭部字段Set-Cookie來給客戶端響應信息。

就像下面服務器返回的Cookie一樣:

Cookie的作用其實就像醫院里面的就診卡一樣,就診卡里面有就診人的基本信息,刷卡之后會根據這些基本信息可以查出在當前醫院里面的歷史就診記錄等更加詳細的信息,這張就診卡就相當于Cookie,而根據就診卡信息獲得的詳細記錄叫做session,每個session里面記錄了就診用戶的許多關鍵信息,例如歷史就診記錄,要做的檢測等等,每一個session都有對應的sessionId,即會話標識,服務器返回給客戶端的Cookie響應就有這個會話標識,然后訪問后續頁面的,根據這個會話標識就能從服務器找到對應的信息進行登錄,這樣刷新頁面就不用在重復登錄了。
下圖所圈的部分就有可能就是一種sessionId。

作者:未見花聞
鏈接:
https://juejin.cn/post/7127647111352418311