get()和post()請求的區別

HTTP協議在現在網絡通信中越來越多的被廣發使用,在HTTP1.0中就有7種請求方式,而在HTTP1.1中更是有8中請求方式,在這當中最常見的就是GET和POST請求。

GET和POST請求主要有5大區別:

  • post請求相對get請求更加安全
  • post發送的數據比get發送的數據更大
  • post能發送更多的數據類型(get只能發送ASCII字符)
  • post比get請求慢
  • post用於修改和寫入數據,get一般用於搜索排序和篩選之類的操作(淘寶,支付寶的搜索查詢都是get提交),目的是資源的獲取,讀取數據

讓我們一個個的來看這5大區別:
一、post請求相對get請求更加安全:
我們所說的安全是相對的安全。從HTTP的報文上來看,GET請求方式將請求信息放在URL(統一資源定位符)的後邊,請求信息和URL之間以?隔開,請求信息的格式爲鍵值對,例如我們在百度上搜索淘寶,百度會給我們顯示如下信息:https://www.baidu.com/s?wd=淘寶&rsv_spt=1 ,這種請求方式將請求信息直接暴露在URL當中,安全性較低。另外從報文的結構上來看,由於請求信息放在URL中,因此請求報文中不需要報文體。
POST請求方式方式將請求信息放在報文體中,要想獲得信息就就必須解析報文,因此安全性較GET方式要高一些。(事實上要獲得報文體中的請求信息也是很容易的,因此安全性上兩者並沒有太多的區別,具體解決傳輸過程中的安全性問題還要靠HTTPS),此外在請求報文中含有報文體。
其次get請求會被CDN緩存,保存在服務器日誌當中以及瀏覽器記錄中。這也成爲get請求不安全的又一原因。
當然細心的同學會看的第五條區別的時候就會問既然POST請求比GET請求更加安全那麼爲什麼在做搜索的時候要用GET而不用POST請求呢?彆着急,我們慢慢往下看。

二、post發送的數據比get發送的數據更大:
其實有很多人對這句話是存在誤解的:

(1)http協議並未規定get和post請求的產長度。
(2)git的請求長度限制是因爲瀏覽器和web服務器限制了URL的長度
(3)不同的瀏覽器和web服務器,限制的最大長度不一樣

誤解:

  1. 首先即使get有長度限制,也是限制的整個URL的長度,而不僅僅是參數值數據長度,http協議從未規定get/post的請求長度限制是多少
  2. 所謂的請求長度限制是由瀏覽器和web服務器決定和設置的,各種瀏覽器和web服務器的設定均不一樣,這依賴於各個瀏覽器廠家的規定或者可以根據web服務器的處理能力來設定。
    三、post比get請求慢:
    1.post請求包含更多的請求頭
    因爲post需要在請求的body部分包含數據,所以會多了幾個數據描述部分的首部字段(如:content-type),這其實是微乎其微的。

2.最重要的一條,post在真正接收數據之前會先將請求頭髮送給服務器進行確認,然後才真正發送數據
post請求的過程:
(1)瀏覽器請求tcp連接(第一次握手)
(2)服務器答應進行tcp連接(第二次握手)
(3)瀏覽器確認,併發送post請求頭(第三次握手,這個報文比較小,所以http會在此時進行第一次數據發送)
(4)服務器返回100 Continue響應
(5)瀏覽器發送數據
(6)服務器返回200 OK響應
get請求的過程:
(1)瀏覽器請求tcp連接(第一次握手)
(2)服務器答應進行tcp連接(第二次握手)
(3)瀏覽器確認,併發送get請求頭和數據(第三次握手,這個報文比較小,所以http會在此時進行第一次數據發送)
(4)服務器返回200 OK響應
也就是說,目測get的總耗是post的2/3左右,這個口說無憑,網上已經有網友進行過測試。

3.get會將數據緩存起來,而post不會
可以做個簡短的測試,使用ajax採用get方式請求靜態數據(比如html頁面,圖片)的時候,如果兩次傳輸的數據相同,第二次以後消耗的時間將會在10ms以內(chrome測試),而post每次消耗的時間都差不多。經測試,chrome和firefox下如果檢測到get請求的是靜態資源,則會緩存,如果是數據,則不會緩存,但是IE什麼都會緩存起來,當然,應該沒有人用post去獲取靜態數據吧,反正我是沒見過。

4.post不能進行管道化傳輸
http權威指南中是這樣說的:http的一次會話需要先建立tcp連接(大部分是tcp,但是其他安全協議也是可以的),然後才能通信,如果 每次連接都只進行一次http會話,那這個連接過程佔的比例太大了!於是出現了持久連接:在http/1.0+中是connection首部中添加keep-alive值,在http/1.1中是在connection首部中添加persistent值,當然兩者不僅僅是命名上的差別,http/1.1中,持久連接是默認的,除非顯示在connection中添加close,否則持久連接不會關閉,而http/1.0+中則恰好相反,除非顯示在connection首部中添加keep-alive,否則在接收數據包後連接就斷開了。
出現了持久連接還不夠,在http/1.1中,還有一種稱爲管道通信的方式進行速度優化:把需要發送到服務器上的所有請求放到輸出隊列中,在第一個請求發送出去後,不等到收到服務器的應答,第二個請求緊接着就發送出去,但是這樣的方式有一個問題:不安全,如果一個管道中有10個連接,在發送出9個後,突然服務器告訴你,連接關閉了,此時客戶端即使收到了前9個請求的答覆,也會將這9個請求的內容清空,也就是說,白忙活了……此時,客戶端的這9個請求需要重新發送。這對於冪等請求還好(比如get,多發送幾次都沒關係,每次都是相同的結果),如果是post這樣的非冪等請求(比如支付的時候,多發送幾次就慘了),肯定是行不通的。
所以,post請求不能通過管道的方式進行通信!很有可能,post請求需要重新建立連接,這個過程不跟完全沒優化的時候一樣了麼?所以,在可以使用get請求通信的時候,不要使用post請求,這樣用戶體驗會更好,當然,如果有安全性要求的話,post會更好。管道化傳輸在瀏覽器端的實現還需考證,貌似默認情況下大部分瀏覽器(除了opera)是不進行管道化傳輸的,除非手動開啓!

四:爲什麼搜索排序和篩選之類的操作多用get():
這時候我們需要從數據庫的層面來看:
 CET請求方式符合冪等性和安全性,(冪等性的定義:對數據庫的一次操作和多次操作獲得的結果是一致的,則認爲符合冪等性。安全性的定義:對數據庫的操作沒有改變數據庫中的數據,則認爲符合安全性),GET請求方式是做查詢操作,因此不會改變數據庫中原有的數據,認爲符合安全性。事實上GET請求可能會出現多次請求的結果(例如在兩次請求中間對數據庫中的數據作了更改),從這來說是不符合冪等性的定義,但是因爲GET請求知識查詢數據庫,不會對數據庫做任何更改,因此也認爲是冪等的。

POST請求方式是既不冪等又不安全,首先POST請求方式往數據庫中提交數據的,因此會改變數據庫中的數據。其次,POST請求方式每次獲得的結果都有可能不一樣,因爲POST請求是作用在上一級的URL上的,則每一次請求都會添加一份新資源(這也是POST和PUT方式的最大區別,PUT方式是冪等的)。
  
注意:在這裏提到的安全性和上一部分提到的安全性不是同一概念,不要混淆。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章