[ASP.NET]HTTP GET與POST的差異

[ASP.NET]HTTP GET與POST的差異
1.GET透過URL的QueryString來傳送想要的資料;POST透過Form submission來傳送想要的資料
2.GET因為透過QueryString來傳送資料,會有URL最大長度限制(2048,可參考[ASP.NET]ASP.NET 4.0 設定QueryString的最大長度);POST則無此限制
3.GET因為透過QueryString來傳送資料,因此也會衍生一些安全性議題,最少敏感性資料不該透過URL來傳送;POST則不會直接洩漏資料於URL上
4.GET會被cache;POST則不會(預設)

HTTP的GET跟POST Method我想大家應該都略知一二,本篇主要將觀念帶一下,並用幾個簡單的範例讓大家了解兩者間的差異,我想在開始之前大家先看看W3C對GET跟POST的定義吧:HTTP/1.1: Method Definitions(請看9.3與9.5兩節)
image

除了以上的定義外,我想以下我翻成比較口語化的用詞吧:
1.GET透過URL的QueryString來傳送想要的資料;POST透過Form submission來傳送想要的資料
2.GET因為透過QueryString來傳送資料,會有URL最大長度限制(可參考[ASP.NET]ASP.NET 4.0 設定QueryString的最大長度);POST則無此限制POST如果透過Send來傳送資料則不會有此問題,若透過URL來傳送一樣會有相同的狀況
3.GET因為透過QueryString來傳送資料,因此也會衍生一些安全性議題,最少敏感性資料不該透過URL來傳送;POST則不會直接洩漏資料於URL上POST如果透過Send來傳送資料則不會有此問題,若透過URL來傳送一樣會有相同的狀況
4.GET會被cache;POST則不會(預設)

以下簡單用幾個範例驗證一下以上四點,以下都使用XMLHttp來實作,以下先描述一下前置準備:

我先在畫面上拉兩個html button,然後分別呼叫SetGET()與SetPOST兩個function,我們可以看到SetGET中,xmlhttp.Open透過URL將Data帶過去,而SetPOST中則透過xmlhttp.Send將Data帶過去GetValue.aspx:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>未命名頁面</title>
    <script language="javascript" >
    var Data = "<root><title1>XML</title1>"+
    "<Records>"+
    "<Record><Column1>col1</Column1><Column2>col2</Column2><Column3>col3</Column3><Column4>col4</Column4><Column5>col5</Column5><Column6>col6</Column6><Record>"+
    "<Record><Column1>col1</Column1><Column2>col2</Column2><Column3>col3</Column3><Column4>col4</Column4><Column5>col5</Column5><Column6>col6</Column6><Record>"+
    "<Record><Column1>col1</Column1><Column2>col2</Column2><Column3>col3</Column3><Column4>col4</Column4><Column5>col5</Column5><Column6>col6</Column6><Record>"+
    "<Record><Column1>col1</Column1><Column2>col2</Column2><Column3>col3</Column3><Column4>col4</Column4><Column5>col5</Column5><Column6>col6</Column6><Record>"+
    "<Record><Column1>col1</Column1><Column2>col2</Column2><Column3>col3</Column3><Column4>col4</Column4><Column5>col5</Column5><Column6>col6</Column6><Record>"+
    "</Records></root>";
    
    function SetGET()
    {
        var xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
        var objXML = new ActiveXObject("Microsoft.XMLDOM");
        var strURL = "GetValue.aspx?Data=";
        xmlhttp.Open('GET', strURL+Data, false);
	    xmlhttp.Send(null);
	    var returnValue = xmlhttp.ResponseText;
	    alert(returnValue);
	}
	
    function SetPOST()
    {
        var xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
        var objXML = new ActiveXObject("Microsoft.XMLDOM");
        var strURL = "GetValue.aspx";
        xmlhttp.Open('POST', strURL, false);
	    xmlhttp.Send(Data);
	    var returnValue = xmlhttp.ResponseText;
	    alert(returnValue);
	}	
	
    </script>
    
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <input id="Button1" type="button" value="GET" onclick="SetGET()" />
        <input id="Button2" type="button" value="POST" onclick="SetPOST()" /></div>
    </form>
</body>
</html>

在GetValue.aspx中我只在Page_Load中加入一行,用來回傳我送過去的ContentLength與Server的時間:

    {
        Response.Write("ContentLength" + Request.InputStream.Length.ToString() + " Time:" + DateTime.Now.ToString());
    }


1.GET透過URL,POST透過Form submission傳送資料
這一項透過以上的預先準備我們就可以看到GET/POST兩者有以下的不同。
image

測試的結果就是這樣:
image

這邊要特別留意的,如果我就是不想遵守GET用URL的原則,我就要直接在Open中用GET,然後Send中還是送出我要的資料,不寫null:
image

我在畫面上多拉了一個按鈕來做這件事,結果發現只要我在Send中有放資料,就會強制以POST來送出我的Form:
image

2.GET透過QueryString來傳送Data會有最大傳送資料限制
這一點請直接參考[ASP.NET]ASP.NET 4.0 設定QueryString的最大長度,而超過最大長度限制會有404的Error:
image

3.GET透過QueryString傳送Data會有安全性問題
這個問題其實只跟QueryString本身有關連,有些人撰寫程式習慣使用以下寫法:

讓人不期然就會想試看看以下寫法,看能不能直接取得老闆的收件匣:

其實我們只要緊記,重要的資料絕對不透過URL來傳送就好,以上面這個範例來說,user的帳號一般我們直接放在Session中就可以免掉這個問題了。

4.GET會被cache,POST預設則不會
使用GET,如果request的網址沒有變動,則Result會是cache的,這意謂著我們取得的不見得是最新的資訊,
 
image

我們以下面這個案例來說明,我前面有提到我在GetValue.aspx中有回傳Server的時間,如果沒有cache的話應該每次按都不同,但我們實際以GET來測試就會發現取得的時間是11:27分,但實際的時間是11:44分,同樣的事情我們用POST來處理就不會有這樣的問題:
image
這個問題在網路上有找到一個案例:

GET、POST與cache的關係

除了以上四點差異外,透過開發者工具,我們在Request Headers/Request Body兩個頁籤也有一些差別,主要是POST有透過Send將資料送出去,因此Content-Length跟Body中都有內容,而GET則沒有,也因此衍生了一些差異,POST因為要多送Request Body中的內容,若以達到相同功能來說,GET會比POST快一些。
image 

以上大概比較了一下GET/POST的差異,希望對大家有幫助,我想依此而衍生出來的issue應該非常非常多,歡迎大家補充。

備註:感謝璉璉大的提醒,為了避免誤會,我把用詞改了一下,POST如果透過Send來傳送資料則不會有此問題,若透過URL來傳送一樣會有與GET相同的狀況


參考資料:
The Definitive Guide to GET vs POST
HTTP/1.1: Method Definitions
Methods GET and POST in HTML forms - what's the difference?
GET、POST與cache的關係

游舒帆 (gipi)

探索原力Co-founder,曾任TutorABC協理與鼎新電腦總監,並曾獲選兩屆微軟最有價值專家 ( MVP ),離開職場後創辦探索原力,致力於協助青少年培養面對未來的能力。認為教育與組織育才其實息息相關,都是在為未來儲備能量,2018年起成立為期一年的專題課程《職涯躍升的關鍵24堂課》,為培養台灣未來的領袖而努力。