最直觀的區別就是GET把參數包含在URL中,POST經過request body傳遞參數。
語義上的區別,get用於獲取數據,post用於提交數據。
get參數有長度限制(受限於url長度,具體的數值取決於瀏覽器和服務器的限制),而post無限制web
w3schools關於這個問題的解答:瀏覽器
GET後退按鈕/刷新無害,POST數據會被從新提交(瀏覽器應該告知用戶數據會被從新提交)。
GET書籤可收藏,POST爲書籤不可收藏。
GET能被緩存,POST不能緩存 。
GET編碼類型application/x-www-form-url,POST編碼類型encodedapplication/x-www-form-urlencoded 或 multipart/form-data。爲二進制數據使用多重編碼。
GET歷史參數保留在瀏覽器歷史中。POST參數不會保存在瀏覽器歷史中。
GET對數據長度有限制,當發送數據時,GET 方法向 URL 添加數據;URL 的長度是受限制的(URL 的最大長度是 2048 個字符)。POST無限制。
GET只容許 ASCII 字符。POST沒有限制。也容許二進制數據。
與 POST 相比,GET 的安全性較差,由於所發送的數據是 URL 的一部分。在發送密碼或其餘敏感信息時毫不要使用 GET !POST 比 GET 更安全,由於參數不會被保存在瀏覽器歷史或 web 服務器日誌中。
GET的數據在 URL 中對全部人都是可見的。POST的數據不會顯示在 URL 中。
參數大小的限制是怎麼回事:HTTP協議對GET和POST都沒有對長度的限制,HTTP協議明確地指出了,HTTP頭和Body都沒有長度的要求。而對於URL長度上的限制,有兩方面的緣由形成:
(1)、(大多數)瀏覽器一般都會限制url長度在2K個字節
(2)、(大多數)服務器最多處理64K大小的url。URL長了,對服務器處理也是一種負擔。本來一個會話就沒有多少數據,如今若是有人惡意地構造幾個幾M大小的URL,並不停地訪問你的服務器。服務器的最大併發數顯然會降低。另外一種攻擊方式是,把告訴服務器Content-Length是一個很大的數,而後只給服務器發一點兒數據,嘿嘿,服務器你就傻等着去吧。哪怕你有超時設置,這種故意的次次訪問超時也能讓服務器吃不了兜着走。有鑑於此,多數服務器出於安全啦、穩定啦方面的考慮,會給URL長度加限制。可是這個限制是針對全部HTTP請求的,與GET、POST沒有關係。 安全不安全和GET、POST沒有關係緩存
其實這些只是一些現象上的區別,若是深刻了解,GET和POST本質上沒有區別的安全
一、現代的Web Server都是支持GET中包含BODY這樣的請求。雖然這種請求不可能從瀏覽器發出,可是如今的Web Server又不是隻給瀏覽器用,已經徹底地超出了HTML服務器的範疇了。服務器
二、HTTP的底層是TCP/IP。因此GET和POST的底層也是TCP/IP,也就是說,GET/POST都是TCP連接。GET和POST能作的事情是同樣同樣的。你要給GET加上request body,給POST帶上url參數,技術上是徹底行的通的。網絡
三、GET產生一個TCP數據包;POST產生兩個TCP數據包。對於GET方式的請求,瀏覽器會把http header和data一併發送出去,服務器響應200(返回數據);而對於POST,瀏覽器先發送header,服務器響應100 continue,瀏覽器再發送data,服務器響應200 ok(返回數據)。
這裏有段引用:併發
由於POST須要兩步,時間上消耗的要多一點,看起來GET比POST更有效。所以Yahoo團隊有推薦用GET替換POST來優化網站性能。但這是一個坑!跳入需謹慎。爲何?app
- GET與POST都有本身的語義,不能隨便混用。
- 據研究,在網絡環境好的狀況下,發一次包的時間和發兩次包的時間差異基本能夠無視。而在網絡環境差的狀況下,兩次包的TCP在驗證數據包完整性上,有很是大的優勢。
- 並非全部瀏覽器都會在POST中發送兩次包,Firefox就只發送一次。
首先強調下:協議不等於實現:協議規定安全在實現裏不必定安全,協議規定冪等在實現裏不必定冪等,協議規定可緩存在實現裏不必定可緩存。curl
咱們一般在討論 GET vs POST 的時候,實際上討論的是 specification,而不是 implementation。什麼是 specification?說白了就是相關的 RFC。implementation 則是全部實現了 specification 中描述的代碼/庫/產品,好比 curl,Python 的 requests 庫,或者 Chrome。POST 請求怎麼發送,根本就不是這段 RFC 在討論的事情。RFC 中只說明瞭 100 continue 和 Expect header 的聯繫,好比你想在 GET 請求裏帶 body,同樣能夠發送 Expect: 100-continue 並等待 100 continue,這是符合標準的。也就是說,『XHR 發送兩個 TCP packets』是關於 implementation 的知識,而不是關於 specification 的知識。你不能說『Chrome 在 AJAX POST 的時候會發兩個 TCP packets,GET 只會發一個』是 GET 和 POST 的區別,正如你不能由於北京 PM 2.5 常常爆表就說國家關於工業廢氣排放的標準有問題。
什麼是RFC呢?post
徵求意見稿(英語:Request For Comments,縮寫爲RFC),是由互聯網工程任務組(IETF)發佈的一系列備忘錄。文件收集了有關互聯網相關信息,以及UNIX和互聯網社區的軟件文件,以編號排定。目前RFC文件是由互聯網協會(ISOC)贊助發行。
簡單理解RFC就是互聯網的規範,咱們一般所說的「協議」就是以RFC的形式存在,而現行的HTTP/1.1規範的RFC有以下幾個: RFC7230, RFC7231, RFC7232, RFC7233, RFC7234,RFC7235。 其中RFC7231裏的Section 4. Request Methods涉及到了幾個HTTP方法,接下來仔細閱讀這一章節。
The request method token is the primary source of request semantics; it indicates the purpose for which the client has made this request and what is expected by the client as a successful result.這裏牽涉到一個很重要的詞語:semantic 「語義」,那麼什麼是語義呢?這一篇文章給出瞭解釋:語法和語義的區別。
一種語言是合法句子的集合。什麼樣的句子是合法的呢?能夠從兩方面來判斷:語法和語義。語法是和文法結構有關,然而語義是和按照這個結構所組合的單詞符號的意義有關。合理的語法結構並不代表語義是合法的。例如咱們常說:我上大學,這個句子是符合語法規則的,也符合語義規則。可是大學上我,雖然符合語法規則,但沒有什麼意義,因此說是不符合語義的。
對於HTTP請求來講,語法是指請求響應的格式,好比請求第一行必須是 方法名 URI 協議/版本 這樣的格式,
語義則定義了這一類型的請求具備什麼樣的性質。好比GET的語義就是「獲取資源」,POST的語義是「處理資源」,那麼在具體實現這兩個方法時,就必須考慮其語義,作出符合其語義的行爲。
固然在符合語法的前提下實現違背語義的行爲也是能夠作到的,好比使用GET方法修改用戶信息,POST獲取資源列表,這樣就只能說這個請求是「合法」的,但不是「符合語義」的。 寫到這裏忽然聯想到XML裏面的兩個概念:Well Formed和Valid,彷佛也正是語法和語義的理念呢。
上文說到方法是請求語義的主要來源,也便是還有次要來源,一些請求Header能夠進一步修飾請求的語義,好比一個帶上了 Range Header的GET請求就變成了部分請求。
RFC7231裏定義了HTTP方法的幾個性質:
- Safe - 安全。這裏的「安全」和一般理解的「安全」意義不一樣,若是一個方法的語義在本質上是「只讀」的,那麼這個方法就是安全的。客戶端向服務端的資源發起的請求若是使用了是安全的方法,就不該該引發服務端任何的狀態變化,所以也是無害的。 此RFC定義,GET, HEAD, OPTIONS 和 TRACE 這幾個方法是安全的。可是這個定義只是規範,並不能保證方法的實現也是安全的,服務端的實現可能會不符合方法語義,正如上文說過的使用GET修改用戶信息的狀況。引入安全這個概念的目的是爲了方便網絡爬蟲和緩存,以避免調用或者緩存某些不安全方法時引發某些意外的後果。User Agent(瀏覽器)應該在執行安全和不安全方法時作出區分對待,並給用戶以提示。
- Idempotent - 冪等冪等的概念是指同一個請求方法執行屢次和僅執行一次的效果徹底相同。按照RFC規範,PUT,DELETE和安全方法都是冪等的。一樣,這也僅僅是規範,服務端實現是否冪等是沒法確保的。引入冪等主要是爲了處理同一個請求重複發送的狀況,好比在請求響應前失去鏈接,若是方法是冪等的,就能夠放心地重發一次請求。這也是瀏覽器在後退/刷新時遇到POST會給用戶提示的緣由:POST語義不是冪等的,重複請求可能會帶來意想不到的後果。
- Cacheable - 可緩存性 顧名思義就是一個方法是否能夠被緩存,此RFC裏GET,HEAD和某些狀況下的POST都是可緩存的,可是絕大多數的瀏覽器的實現裏僅僅支持GET和HEAD。關於緩存的更多內容能夠去看RFC7234。
在這三個特性裏一直在強調同一個事情,那就是協議不等於實現:協議規定安全在實現裏不必定安全,協議規定冪等在實現裏不必定冪等,協議規定可緩存在實現裏不必定可緩存。這其實就是上面那個做者提到的specification和implementation的關係。
走到這一步,其實就明白了要理解這兩個方法的區別,本質上是 「語義」的對比而不是「語法」的對比,是「Specification」的對比而不是「Implementation」的對比 。