基於c#的http協議學習
轉載於https://www.cnblogs.com/jiang08/articles/3946015.html
跪謝!
在TCP/IP體系結構中,HTTP屬於應用層協議,位於TCP/IP協議的頂層。瀏覽Web時,瀏覽器通過HTTP協議與Web伺服器交換資訊。這些資訊(文件)型別的格式由MIME定義。
HTTP協議具有以下的特點:
1. HTTP按客戶/伺服器模式工作 HTTP支援客戶(一般情況是瀏覽器)與伺服器的通訊,相互傳輸資料。 HTTP定義的事務處理由以下四步組成:
· 客戶與伺服器建立連線;
· 客戶向伺服器提出請求;
· 如果請求被接受,則伺服器送回響應,在響應中包括狀態碼和所需的檔案;
· 客戶與伺服器斷開連線
一次HTTP操作稱為一次事務(transaction)。 |
2. HTTP是無狀態的 也就是說,瀏覽器和伺服器每進行 一次HTTP
3. HTTP使用元資訊作為頭標 HTTP對所有事務都加了頭標(header)。也就是說,在主要資料前加上一塊資訊,稱為元資訊(metainformation)。它使伺服器能夠提供正在傳送資料的有關資訊。例如,傳送物件是哪種型別,是用哪種語言書寫的等。 從功能上講,HTTP支援四類元資訊:一般資訊頭標、請求頭標、響應頭標和實體頭標。
4. HTTP支援兩種請求和響應格式 HTTP由不同的兩部分組成,一是從瀏覽器發往伺服器的請求,二是伺服器對客戶的響應。 HTTP支援兩種請求和響應,即簡單請求與完全請求和簡單響應與完全響應。
5. HTTP是基於文字的簡單協議
HTTP的常用請求方法:
方法 |
說明 |
GET |
請求讀取一個Web頁面 |
HEAD |
請求讀取一個Web頁面的頭標 |
PUT |
請求儲存一個Web頁面 |
POST |
附加到命名資源中 |
DELETE |
刪除Web頁面 |
LINK |
連線兩個已有資源 |
UNLINK |
取消兩個資源之間的已有連線 |
HTTP請求的格式如下所示:
<request-line> //請求行(request line),用來說明請求型別、要訪問的資源以及使用的HTTP版本
<headers>//首部(header)小節,用來說明伺服器要使用的附加資訊
<blank line>//首部之後是一個空行
[<request-body>] 其他資料[稱之為主體(body)]
只要在Web瀏覽器上輸入一個URL,瀏覽器就將基於該URL向伺服器傳送一個GET請求,以告訴伺服器獲取並返回什麼資源。對於URL為XXX的GET請求如下所示:
GET / HTTP/1.1 //該請求是GET請求。該行的第二部分是一個斜槓(/)用來說明請求的是該域名的根目錄。該行的最後一部分說明使用的是HTTP 1.1版本
Host: XXX //首部HOST將指出請求的目的地。結合HOST和上一行中的斜槓(/),可以通知伺服器請求的是XXX
User-Agent: Mozilla/5.0 (Windows; U; WindowsNT 5.1; en-US; rv:1.7.6) //第三行中包含的是首部User-Agent,伺服器端和客戶端指令碼都能夠訪問它,它是瀏覽器型別檢測邏輯的重要基礎。該資訊由你使用的瀏覽器來定義(在本例中是Firefox 1.0.1),並且在每個請求中將自動傳送。
Gecko/20050225 Firefox/1.0.1 //在本例中是Firefox 1.0.1
Connection: Keep-Alive //首部Connection,通常將瀏覽器操作設定為Keep-Alive)
//注意,在最後一個首部之後有一個空行。即使不存在請求主體,這個空行也是必需的。
如果要獲取一個諸如XXX/xxx的XXX域內的頁面,那麼該請求可能類似於:
GET /xxx/ HTTP/1.1
Host: XXX
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6)
Gecko/20050225 Firefox/1.0.1
Connection: Keep-Alive
//空行
注意只有第一行的內容發生了變化,它只包含URL中XXX後面的部分。
要傳送GET請求的引數,則必須將這些額外的資訊附在URL本身的後面。其格式類似於:
URL ?name1=value1&name2=value2&..&nameN=valueN
該資訊稱之為查詢字串(query string),它將會複製在HTTP請求的請求行中,如下所示:
GET /xxx/?name=Professional%20Ajax HTTP/1.1
Host: XXX
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6)
Gecko/20050225 Firefox/1.0.1
Connection: Keep-Alive
另一方面,POST請求在請求主體中為伺服器提供了一些附加的資訊。通常,當填寫一個線上表單並提交它時,這些填入的資料將以POST請求的方式傳送給伺服器。
POST / HTTP/1.1//請求行開始處的GET改為了POST,以示不同。
Host: XXX //URL
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6)
Gecko/20050225 Firefox/1.0.1
Content-Type:application/x-www-form-urlencoded //Content-Type說明了請求主體的內容是如何編碼的,瀏覽器始終以application/x-www-form- urlencoded的格式編碼來傳送資料,這是針對簡單URL編碼的MIME型別(text/html)
Content-Length: 40 //Content-Length說明了請求主體的位元組數
Connection: Keep-Alive
//首部Connection後是一個空行,再後面就是請求主體
name=Professional%20Ajax&publisher=Wiley //以鍵值對的形式給出,其中name是Professional Ajax,publisher是Wiley。你可以以同樣的格式來組織URL的查詢字串引數。
正如前面所提到的,還有其他的HTTP請求型別,它們遵從的基本格式與GET請求和POST請求相同。下一步我們來看看伺服器將對HTTP請求傳送什麼響應。
HTTP響應
如下所示,HTTP響應的格式與請求的格式十分類似:
<status-line>
<headers>
<blank line>
[<response-body>]
響應中唯一的區別在於第一行中用狀態資訊代替了請求資訊。狀態行(statusline)通過提供一個狀態碼來說明所請求的資源情況。
以下就是一個HTTP響應的例子:
HTTP/1.1200 OK //狀態行給出的HTTP狀態程式碼是200,以及訊息OK
Date: Sat, 31 Dec 200523:59:59 GMT //狀態行之後是一些首部,通常,伺服器會返回一個名為Date的首部,用來說明響應生成的日期和時間(伺服器通常還會返回一些關於其自身的資訊,儘管並非是必需的)
//接下來的兩個首部大家應該熟悉,就是與POST請求中一樣的Content-Type和Content-Length。在本例中,首部Content-Type指定了MIME型別HTML(text/html),其編碼型別是ISO-8859-1(這是針對美國英語資源的編碼標準)
Content-Type: text/html;charset=ISO-8859-1
Content-Length: 122
<html>
<head>
<title>Wrox Homepage</title>
</head>
<body>
<!-- body goes here-->
</body>
</html>
狀態行始終包含的是狀態碼和相應的簡短訊息,以避免混亂。最常用的狀態碼有:
· 200 (OK): 找到了該資源,並且一切正常。
· 304 (NOT MODIFIED): 該資源在上次請求之後沒有任何修改。這通常用於瀏覽器的快取機制。
· 401 (UNAUTHORIZED):客戶端無權訪問該資源。這通常會使得瀏覽器要求使用者輸入使用者名稱和密碼,以登入到伺服器。
· 403 (FORBIDDEN):客戶端未能獲得授權。這通常是在401之後輸入了不正確的使用者名稱或密碼。
· 404 (NOT FOUND):在指定的位置不存在所申請的資源。
響應主體所包含的就是所請求資源的HTML原始檔(儘管還可能包含純文字或其他資源型別的二進位制資料)。瀏覽器將把這些資料顯示給使用者。注意,這裡並沒有指明針對該響應的請求型別,不過這對於伺服器並不重要。客戶端知道每種型別的請求將返回什麼型別的資料,並決定如何使用這些資料。
HTTP認證
◆基本認證 basic authentication
客戶端對於每一個realm,通過提供使用者名稱和密碼來進行認證的方式。
※ 包含密碼的明文傳遞
基本認證步驟:
1. 客戶端訪問一個受http基本認證保護的資源。
2. 伺服器返回401狀態,要求客戶端提供使用者名稱和密碼進行認證。
401 Unauthorized
WWW-Authenticate: Basic realm="WallyWorld"
3. 客戶端將輸入的使用者名稱密碼用Base64進行編碼後,採用非加密的明文方式傳送給伺服器。
Authorization: Basic xxxxxxxxxx.
4. 如果認證成功,則返回相應的資源。如果認證失敗,則仍返回401狀態,要求重新進行認證。
特記事項:
1. Http是無狀態的,同一個客戶端對同一個realm內資源的每一個訪問會被要求進行認證。
2. 客戶端通常會快取使用者名稱和密碼,並和authenticationrealm一起儲存,所以,一般不需要你重新輸入使用者名稱和密碼。
3. 以非加密的明文方式傳輸,雖然轉換成了不易被人直接識別的字串,但是無法防止使用者名稱密碼被惡意盜用。
特記事項:
1. Http是無狀態的,同一個客戶端對同一個realm內資源的每一個訪問會被要求進行認證。
2. 客戶端通常會快取使用者名稱和密碼,並和authenticationrealm一起儲存,所以,一般不需要你重新輸入使用者名稱和密碼。
3. 以非加密的明文方式傳輸,雖然轉換成了不易被人直接識別的字串,但是無法防止使用者名稱密碼被惡意盜用。
◆ 摘要認證 digest authentication
伺服器端以nonce進行質詢,客戶端以使用者名稱,密碼,nonce,HTTP方法,請求的URI等資訊為基礎產生的response資訊進行認證的方式。
※ 不包含密碼的明文傳遞
摘要認證步驟:
1. 客戶端訪問一個受http摘要認證保護的資源。
2. 伺服器返回401狀態以及nonce等資訊,要求客戶端進行認證。
HTTP/1.1401 Unauthorized
WWW-Authenticate: Digest
realm="[email protected]",//響應中包含資訊
qop="auth,auth-int",
nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093",//響應中包含的資訊
opaque="5ccc069c403ebaf9f0171e9517f40e41"
3. 客戶端將以使用者名稱,密碼,nonce值,HTTP方法, 和被請求的URI為校驗值基礎而加密(預設為MD5演算法)的摘要資訊返回給伺服器。
認證必須的五個情報:
・ realm : 響應中包含資訊
・ nonce : 響應中包含資訊
・ username : 使用者名稱
・ digest-uri : 請求的URI
・ response : 以上面四個資訊加上密碼資訊,使用MD5演算法得出的字串。
特記事項:
1. Http是無狀態的,同一個客戶端對同一個realm內資源的每一個訪問會被要求進行認證。
2. 客戶端通常會快取使用者名稱和密碼,並和authenticationrealm一起儲存,所以,一般不需要你重新輸入使用者名稱和密碼。
3. 以非加密的明文方式傳輸,雖然轉換成了不易被人直接識別的字串,但是無法防止使用者名稱密碼被惡意盜用。
Authorization: Digest
username="Mufasa", ← 客戶端已知資訊
realm="[email protected]", ← 伺服器端質詢響應資訊
nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093", ← 伺服器端質詢響應資訊
uri="/dir/index.html", ← 客戶端已知資訊
qop=auth, ← 伺服器端質詢響應資訊
nc=00000001, ← 客戶端計算出的資訊
cnonce="0a4f113b", ← 客戶端計算出的客戶端nonce
response="6629fae49393a05397450978507c4ef1", ← 最終的摘要資訊 ha3
opaque="5ccc069c403ebaf9f0171e9517f40e41" ← 伺服器端質詢響應資訊
特記事項:
1. Http是無狀態的,同一個客戶端對同一個realm內資源的每一個訪問會被要求進行認證。
2. 客戶端通常會快取使用者名稱和密碼,並和authenticationrealm一起儲存,所以,一般不需要你重新輸入使用者名稱和密碼。
3. 以非加密的明文方式傳輸,雖然轉換成了不易被人直接識別的字串,但是無法防止使用者名稱密碼被惡意盜用。
4. 如果認證成功,則返回相應的資源。如果認證失敗,則仍返回401狀態,要求重新進行認證。
特記事項:
1. 避免將密碼作為明文在網路上傳遞,相對提高了HTTP認證的安全性。
2. 當用戶為某個realm首次設定密碼時,伺服器儲存的是以使用者名稱,realm,密碼為基礎計算出的雜湊值(ha1),而非密碼本身。
3. 如果qop=auth-int,在計算ha2時,除了包括HTTP方法,URI路徑外,還包括請求實體主體,從而防止PUT和POST請求表示被人篡改。
4. 但是因為nonce本身可以被用來進行摘要認證,所以也無法確保認證後傳遞過來的資料的安全性。
※nonce:隨機字串,每次返回401響應的時候都會返回一個不同的nonce。
※nounce:隨機字串,每個請求都得到一個不同的nounce。
※ MD5(Message Digestalgorithm 5,資訊摘要演算法)
① 使用者名稱:realm:密碼 ⇒ha1
② HTTP方法:URI ⇒ha2
③ha1:nonce:nc:cnonce:qop:ha2 ⇒ha3
特記事項:
1. Http是無狀態的,同一個客戶端對同一個realm內資源的每一個訪問會被要求進行認證。
2. 客戶端通常會快取使用者名稱和密碼,並和authenticationrealm一起儲存,所以,一般不需要你重新輸入使用者名稱和密碼。
3. 以非加密的明文方式傳輸,雖然轉換成了不易被人直接識別的字串,但是無法防止使用者名稱密碼被惡意盜用。
◆ WSSE(WS-Security)認證
WSSE UsernameToken
伺服器端以nonce進行質詢,客戶端以使用者名稱,密碼,nonce,HTTP方法,請求的URI等資訊為基礎產生的response資訊進行認證的方式。
※ 不包含密碼的明文傳遞
WSSE認證步驟:
1. 客戶端訪問一個受WSSE認證保護的資源。
2. 伺服器返回401狀態,要求客戶端進行認證。
HTTP/1.1401 Unauthorized
WWW-Authenticate: WSSE
realm="[email protected]",
profile="UsernameToken" ← 伺服器期望你用UsernameToken規則生成迴應
※ UsernameToken規則:客戶端生成一個nonce,然後根據該nonce,密碼和當前日時來算出雜湊值。
3. 客戶端將生成一個nonce值,並以該nonce值,密碼,當前日時為基礎,算出雜湊值返回給服務器。
Authorization: WSSE profile="UsernameToken"
X-WSSE:UsernameToken
username="Mufasa",
PasswordDigest="Z2Y......",
Nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093",
Created="2010-01-01T09:00:00Z"
4. 如果認證成功,則返回相應的資源。如果認證失敗,則仍返回401狀態,要求重新進行認證。
特記事項:
1. 避免將密碼作為明文在網路上傳遞。
2. 不需要在伺服器端作設定。
3. 伺服器端必須儲存密碼本身,否則無法進行身份驗證。
特記事項:
1. Http是無狀態的,同一個客戶端對同一個realm內資源的每一個訪問會被要求進行認證。
2. 客戶端通常會快取使用者名稱和密碼,並和authenticationrealm一起儲存,所以,一般不需要你重新輸入使用者名稱和密碼。
3. 以非加密的明文方式傳輸,雖然轉換成了不易被人直接識別的字串,但是無法防止使用者名稱密碼被惡意盜用。
與HTTP相關類的簡介
WebRequest類
WebRequest 是 .NET Framework 的用於訪問 Internet 資料的請求/響應模型的抽象基類。使用該請求/響應模型的應用程式可以用協議不可知的方式從 Internet 請求資料。在這種方式下,應用程式處理 WebRequest 類的例項,而協議特定的子類則執行請求的具體細節。
請求從應用程式傳送到某個特定的 URI,如伺服器上的 Web 頁。URI 從一個為應用程式註冊的 WebRequest 子代列表中確定要建立的適當子類。註冊 WebRequest 子代通常是為了處理某個特定的協議(如 HTTP 或 FTP),但是也可以註冊它以處理對特定伺服器或伺服器上的路徑的請求。
由於 WebRequest 類是一個抽象類,所以 WebRequest 例項在執行時的實際行為由 WebRequest.Create 方法所返回的子類確定。
注意 使用 Create 方法初始化新的 WebRequest 例項。不要使用 WebRequest 建構函式。
下面的示例說明如何建立 WebRequest 例項並返回響應。
// Initialize the WebRequest.
WebRequest myRequest = WebRequest.Create("xxx");
// Return the response.
WebResponse myResponse = myRequest.GetResponse();
// Code to use the WebResponse goes here.
// Close the response to free resources.
myResponse.Close();
WebResponse 類
WebResponse 類是抽象(在 Visual Basic 中為 MustInherit)基類,協議特定的響應類從該抽象基類派生。應用程式可以使用 WebResponse 類的例項以協議不可知的方式參與請求和響應事務,而從 WebResponse 派生的協議特定的類攜帶請求的詳細資訊。
客戶端應用程式不直接建立 WebResponse 物件,而是通過呼叫 WebRequest 例項上的GetResponse 方法來建立它。
下面的示例從 WebRequest 建立 WebResponse 例項。
// Initialize the WebRequest.
WebRequest myRequest = WebRequest.Create("xxx");
// Return the response.
WebResponse myResponse = myRequest.GetResponse();
// Code to use the WebResponse goes here.
// Close the response to free resources.
myResponse.Close();
HttpWebRequest 類
HttpWebRequest 類對 WebRequest 中定義的屬性和方法提供支援,也對使使用者能夠直接與使用 HTTP 的伺服器互動的附加屬性和方法提供支援。
不要使用 HttpWebRequest 建構函式。使用 WebRequest.Create 方法初始化HttpWebRequest 的一個新例項。如果 URI 的方案是 http:// 或 https://,則 Create將返回 HttpWebRequest 例項。
GetResponse 方法向 RequestUri 屬性中指定的 Internet 資源發出同步請求並返回包含該響應的 HttpWebResponse 例項。可以使用 BeginGetResponse 和EndGetResponse 方法對 Internet 資源發出非同步請求。
當要向 Internet 資源傳送資料時,GetRequestStream 方法返回用於傳送資料的Stream例項。BeginGetRequestStream 和 EndGetRequestStream 方法提供對傳送資料流的非同步訪問。
下面的示例為 URI xxx 建立 HttpWebRequest
HttpWebRequest myReq = (HttpWebRequest)WebRequest.Create("xxx");
HttpWebResponse類
此類包含對 WebResponse 類中的屬性和方法的 HTTP 特定用法的支援。HttpWebResponse 類用於生成傳送 HTTP 請求和接收 HTTP 響應的 HTTP 獨立客戶端應用程式。
注意:不要混淆 HttpWebResponse 和 HttpResponse;後者用於 ASP.NET 應用程式,而且它的方法和屬性是通過 ASP.NET 的內部 HttpResponse 物件公開的。
決不要直接建立 HttpWebResponse 類的例項。而應當使用通過呼叫HttpWebRequest.GetResponse 所返回的例項。
從 Internet 資源返回的公共標頭資訊公開為該類的屬性。有關完整的列表,請參見下表。可以從 Headers 屬性以名稱/值對的形式讀取其他標頭。
下表顯示可以通過 HttpWebResponse 類的屬性使用的公共 HTTP 標頭。
標頭 |
屬性 |
Content-Encoding |
ContentEncoding |
Content-Length |
ContentLength |
Content-Type |
ContentType |
Last-Modified |
LastModified |
伺服器 |
Server |
通過呼叫 GetResponseStream 方法,以 Stream 的形式返回來自 Internet 資源的響應的內容。
下面的示例返回 HttpWebRequest 的 HttpWebResponse:
HttpWebRequest HttpWReq =(HttpWebRequest)WebRequest.Create("xxx");
HttpWebResponse HttpWResp =(HttpWebResponse)HttpWReq.GetResponse();
// Insert code that uses the response object.
HttpWResp.Close()
URI類
URI 是 Internet 上可由應用程式使用的資源的簡潔表示形式。Uri 類定義了屬性和方法來處理 URI,包括分析、比較和組合。Uri 類屬性是隻讀的,修改 Uri 例項需使用UriBuilder 類。
Uri 類只儲存絕對 URI。相對 URI(例如“/new/index.htm”)必須相對於基 URI 展開,這樣才是絕對的。提供了 MakeRelative 方法在必要時將絕對 URI 轉換為相對 URI。
URI 由轉義編碼儲存為規範化 URI,所有 ASCII 值大於 127 的字元都被替換為它們的等效十六進位制數。為使 URI 具有規範化格式,Uri 建構函式執行以下步驟。
· 將 URI 方案轉換為小寫。
· 將主機名轉換為小寫。
· 移除預設埠號和空埠號。
· 移除多餘的段(如“/”和“/test”段)以簡化 URI。
使用 ToString 方法,可以將 Uri 類的內容從轉義編碼的 URI 引用轉換為可讀的 URI 引用。
一些 URI 包括段識別符號或查詢。段識別符號是 URI 中跟在數字符號 (#) 後的任何文字,儲存在 Fragment 屬性中。查詢資訊是 URI 中跟在問號 (?) 後的任何文字,儲存在 Query 屬性中。
注意:URI 類支援使用以下格式的 IP 地址:四組表示法的 IPv4 協議和冒號分隔的十六進位制 IPv6 協議。請記住在 IPv6 地址兩邊括上方括號,如 http://[::1]。
下面的示例建立 Uri 類的例項,並用它來建立 WebRequest。
Uri siteUri = new Uri("xxx");
WebRequest wr = WebRequest.Create(siteUri);