Winform模擬post請求和get請求登陸網站

引言

最近有朋友問如何用winform模擬post請求,而後登陸網站,稍微想了一下,大體就是對http報文的相關信息的封裝,而後請求網站登陸地址的樣子。發現本身的博客中對這部分只是也沒總結,就藉着這股風,總結一下http報文的相關知識吧。javascript

HTTP定義

超文本傳輸協議 (HTTP-Hypertext transfer protocol) 是一種詳細規定了瀏覽器和萬維網服務器之間互相通訊的規則,經過因特網傳送萬維網文檔的數據傳送協議。html

 這裏對http的具體內容就再也不介紹了,主要分析http報文信息。java

http報文分爲:請求報文和響應報文。jquery

HTTP請求報文

一個Http請求報文由請求行(request line)、請求頭部(header)、空行和請求數據4個部分組成,請求報文個格式以下:web

Post請求ajax

弄一個簡單的登陸頁面,使用ajax發送post請求,在IE下瀏覽,F12分析一下它的請求報文:瀏覽器

頁面代碼:安全

1 <!DOCTYPE html>
 2 <html xmlns="http://www.w3.org/1999/xhtml">
 3 <head>
 4     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
 5     <title>wolfy信息系統登陸</title>
 6     <script type="text/javascript" src="Scripts/jquery-1.11.0.js"></script>
 7     <script type="text/javascript">
 8         $(function () {
 9             $("#btnLogin").click(function () {
10                 var name = $("#txtUserName").val();
11                 var pwd = $("#txtPwd").val();
12                 $.ajax({
13                     url: "Ashx/Login.ashx",
14                     data: "name=" + name + "&pwd=" + pwd,
15                     type: "POST",
16                     dataType: "text",
17                     success: function (msg) {
18                         if (msg=="1") {
19                             $("#divMsg").html("登陸成功");
20                         } else {
21                             $("#divMsg").html("登陸失敗");
22                         }
23                     }
24 
25 
26                 });
27             });
28         });
29     </script>
30 </head>
31 <body>
32     <div style="text-align:center;">
33         <table>
34             <tr>
35                 <td>用戶名:</td>
36                 <td><input type="text" id="txtUserName" name="name" value="admin" /></td>
37             </tr>
38             <tr>
39                 <td>密碼:</td>
40                 <td><input type="password" id="txtPwd" name="name" value="admin" /></td>
41             </tr>
42             <tr>
43                 <td colspan="2"><input type="button" id="btnLogin" name="name" value="登陸" /></td>
44             </tr>
45         </table>
46         <div id="divMsg"></div>
47     </div>
48 </body>
49 </html>
1 <!DOCTYPE html>
 2 <html xmlns="http://www.w3.org/1999/xhtml">
 3 <head>
 4     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
 5     <title>wolfy信息系統登陸</title>
 6     <script type="text/javascript" src="Scripts/jquery-1.11.0.js"></script>
 7     <script type="text/javascript">
 8         $(function () {
 9             $("#btnLogin").click(function () {
10                 var name = $("#txtUserName").val();
11                 var pwd = $("#txtPwd").val();
12                 $.ajax({
13                     url: "Ashx/Login.ashx",
14                     data: "name=" + name + "&pwd=" + pwd,
15                     type: "POST",
16                     dataType: "text",
17                     success: function (msg) {
18                         if (msg=="1") {
19                             $("#divMsg").html("登陸成功");
20                         } else {
21                             $("#divMsg").html("登陸失敗");
22                         }
23                     }
24 
25 
26                 });
27             });
28         });
29     </script>
30 </head>
31 <body>
32     <div style="text-align:center;">
33         <table>
34             <tr>
35                 <td>用戶名:</td>
36                 <td><input type="text" id="txtUserName" name="name" value="admin" /></td>
37             </tr>
38             <tr>
39                 <td>密碼:</td>
40                 <td><input type="password" id="txtPwd" name="name" value="admin" /></td>
41             </tr>
42             <tr>
43                 <td colspan="2"><input type="button" id="btnLogin" name="name" value="登陸" /></td>
44             </tr>
45         </table>
46         <div id="divMsg"></div>
47     </div>
48 </body>
49 </html>

 

通常處理頁代碼:服務器

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Web;
 5 
 6 namespace Wolfy.LoginWeb.Ashx
 7 {
 8     /// <summary>
 9     /// Login 的摘要說明
10     /// </summary>
11     public class Login : IHttpHandler
12     {
13 
14         public void ProcessRequest(HttpContext context)
15         {
16             context.Response.ContentType = "text/plain";
17             //接收用戶名和密碼
18             string name = context.Request.Form["name"];
19             string pwd = context.Request.Form["pwd"];
20             if (string.IsNullOrEmpty(name) || string.IsNullOrEmpty(pwd))
21             {
22                 context.Response.Write("2");
23             }
24             else
25             {
26                 if (name == "admin" && pwd == "admin")
27                 {
28                     //登陸成功記入cookie
29                     context.Response.Cookies["n"].Value = name;
30                     context.Response.Cookies["n"].Expires = DateTime.Now.AddDays(7);
31                     context.Response.Cookies["p"].Value = pwd;
32                     context.Response.Cookies["p"].Expires = DateTime.Now.AddDays(7);
33                     context.Response.Write("1");
34                 }
35                 else
36                 {
37                     context.Response.Write("2");
38                 }
39             }
40         }
41 
42         public bool IsReusable
43         {
44             get
45             {
46                 return false;
47             }
48         }
49     }
50 }

 

    Accept:瀏覽器可接受的MIME類型。
    Accept-Charset:瀏覽器可接受的字符集。
    Accept-Encoding:瀏覽器可以進行解碼的數據編碼方式,好比gzip。Servlet可以向支持gzip的瀏覽器返回經gzip編碼的HTML頁面。許多情形下這能夠減小5到10倍的下載時間。
    Accept-Language:瀏覽器所但願的語言種類,當服務器可以提供一種以上的語言版本時要用到。
    Authorization:受權信息,一般出如今對服務器發送的WWW - Authenticate頭的應答中。
    Connection:表示是否須要持久鏈接。若是Servlet看到這裏的值爲「Keep - Alive」,或者看到請求使用的是HTTP 1.1(HTTP 1.1默認進行持久鏈接),它就能夠利用持久鏈接的優勢,當頁面包含多個元素時(例如Applet,圖片),顯著地減小下載所須要的時間。要實現這一點,Servlet須要在應答中發送一個  Content-Length頭,最簡單的實現方法是:先把內容寫入ByteArrayOutputStream,而後在正式寫出內容以前計算它的大小。
    Content-Length:表示請求消息正文的長度。
    Cookie:這是最重要的請求頭信息之一。cookie

    From:請求發送者的email地址,由一些特殊的Web客戶程序使用,瀏覽器不會用到它。
    Host:初始URL中的主機和端口。
    If-Modified-Since:只有當所請求的內容在指定的日期以後又通過修改才返回它,不然返回304「Not Modified」應答。
    Pragma:指定「no-cache」值表示服務器必須返回一個刷新後的文檔,即便它是代理服務器並且已經有了頁面的本地拷貝。
    Referer:包含一個URL,用戶從該URL表明的頁面出發訪問當前請求的頁面。
    User-Agent:瀏覽器類型,若是Servlet返回的內容與瀏覽器類型有關則該值很是有用。
    UA-Pixels,UA-Color,UA-OS,UA-CPU:由某些版本的IE瀏覽器所發送的非標準的請求頭,表示屏幕大小、顏色深度、操做系統和CPU類型。

請求正文

從這裏能夠發現,請求正文就是咱們要向服務器post提交的數據。

Get請求

將ajax的請求方式換成"GET",那麼get方式請求報文是怎樣的呢?

從上圖能夠看出post和get請求報文的區別,post提交的數據是在請求正文中,而get提交的數據是在url中。

Http響應報文

從上圖能夠看出,響應報文和請求報文很是類似,包括:狀態行、消息報文、響應正文。

在響應報文中第一行中用狀態信息代替了請求信息,狀態行(status)經過提供一個狀態嗎來講明所請求的資源狀況。

狀態行的格式爲:

HTTP-Version Status-Code Reason-Phrase CRLF

其中,HTTP-Version表示服務器HTTP協議的版本;Status-Code表示服務器發回的響應狀態碼;Reason-Phrase表示狀態碼的文本描述。狀態碼由三位數字組成,第一個數字定義了響應的類別,且有5種可能取值:

    • 1xx:指示信息——表示請求已接收,繼續處理。
    • 2xx:成功——表示請求已被成功接收、理解、接受。好比200
    • 3xx:重定向——要完成請求必須進行更進一步的操做。
    • 4xx:客戶端錯誤——請求有語法錯誤或請求沒法實現。
    • 5xx:服務端錯誤——服務器未能實現合法的請求。

常見的狀態碼:

    • 200 OK:客戶端請求成功。
    • 400 Bad Request:客戶端請求有語法錯誤,不能被服務器所理解。
    • 401 Unauthorized:請求未經受權,這個狀態代碼必須和WWW-Authenticate報頭域一塊兒使用。
    • 403 Forbidden:服務器收到請求,可是拒絕提供服務。
    • 404 Not Found:請求資源不存在。
    • 500 Internal Server Error:服務器發生不可預期的錯誤。
    • 503 Server Unavailable:服務器當前不能處理客戶端的請求,一段時間後可能回覆正常。

 GET和Post的區別

GET方式,請求的數據會在URL以後(就是將數據放置在http請求<request-line>中),以問號分割URL和傳輸數據,多個參數使用&鏈接,若是數據是英文字母/數字,原樣發送,若是是空格,轉換爲+,若是是中文或其餘字符,則直接將字符串用Base64加密,在url中最多見的:%E4%BD%A0%E5%A5%BD,這種東東%XX中的XX爲該符號以16進製表示的ASCII。

Post方式,把提交的數據防止在http的包體<request-body>中。上文請求正文中的數據就是實際傳輸的數據。

所以,get提交的數據會在地址欄中顯示出來,而post不會。

GET:不一樣瀏覽器和服務器對URL長度有限制。例如IE對url的限制是2083字節。其餘瀏覽器如Netscape、FireFox等,理論上沒有長度限制,其限制取決於操做系統的支持。

 所以對於get提交時,傳輸數據就會收到url長度限制。

POST:因爲不是經過url傳值,理論上是不受限的。但實際各個web服務器會規定對post提交數據大小進行限制。Apache、iis6都有各自的配置。

(以上參考文章:http://www.cnblogs.com/biyeymyhjob/archive/2012/07/28/2612910.html

get方式和post方式比較在安全性上較低,因此比較隱私性的東東通常採用post方式提交。誰也不肯意將本身用戶名和密碼在url中顯示出來吧?

 winform登陸模擬post方式登陸

上面參考網絡資源對http請求與響應報文又學習了一下,如今模擬post方式登陸。get方式大體類似,再也不贅述。

post類

 1 using System;
 2 using System.Collections.Generic;
 3 using System.IO;
 4 using System.IO.Compression;
 5 using System.Linq;
 6 using System.Net;
 7 using System.Text;
 8 using System.Threading.Tasks;
 9 
10 namespace Wolfy.LoginTest
11 {
12     public class Post
13     {
14         /// <summary>
15         /// 得到post請求後響應的數據
16         /// </summary>
17         /// <param name="postUrl">請求地址</param>
18         /// <param name="referUrl">請求引用地址</param>
19         /// <param name="data">請求帶的數據</param>
20         /// <returns>響應內容</returns>
21         public string PostLogin(string postUrl, string referUrl, string data)
22         {
23             string result = "";
24             try
25             {
26                 //命名空間System.Net下的HttpWebRequest類
27                 HttpWebRequest request = (HttpWebRequest)WebRequest.Create(postUrl);
28                 //參照瀏覽器的請求報文 封裝須要的參數 這裏參照ie9
29                 //瀏覽器可接受的MIME類型
30                 request.Accept = "text/plain, */*; q=0.01";
31                 //包含一個URL,用戶從該URL表明的頁面出發訪問當前請求的頁面
32                 request.Referer = referUrl;
33                 //瀏覽器類型,若是Servlet返回的內容與瀏覽器類型有關則該值很是有用
34                 request.UserAgent = "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET4.0C; .NET4.0E)";
35                 request.ContentType = "application/x-www-form-urlencoded; charset=UTF-8";
36                 //請求方式
37                 request.Method = "POST";
38                 //是否保持常鏈接
39                 request.KeepAlive = false;
40                 request.Headers.Add("Accept-Encoding", "gzip, deflate");
41                 //表示請求消息正文的長度
42                 request.ContentLength = data.Length;
43                 44                 Stream postStream = request.GetRequestStream();
45                 byte[] postData = Encoding.UTF8.GetBytes(data);
46                 //將傳輸的數據,請求正文寫入請求流
47                 postStream.Write(postData, 0, postData.Length);
48                 postStream.Dispose();
49                 //響應
50                 HttpWebResponse response = (HttpWebResponse)request.GetResponse();
51                 //判斷響應的信息是否爲壓縮信息 若爲壓縮信息解壓後返回
52                 if (response.ContentEncoding == "gzip")
53                 {
54                     MemoryStream ms = new MemoryStream();
55                     GZipStream zip = new GZipStream(response.GetResponseStream(), CompressionMode.Decompress);
56                     byte[] buffer = new byte[1024];
57                     int l = zip.Read(buffer, 0, buffer.Length);
58                     while (l > 0)
59                     {
60                         ms.Write(buffer, 0, l);
61                         l = zip.Read(buffer, 0, buffer.Length);
62                     }
63                     ms.Dispose();
64                     zip.Dispose();
65                     result = Encoding.UTF8.GetString(ms.ToArray());
66                 }
67                 return result;
68             }
69             catch (Exception)
70             {
71 
72                 throw;
73             }
74         }
75     }
76 }

 

 請求中相關屬性的值,你能夠在瀏覽器,F12中,將對應的值,複製粘貼就能夠,這東西不須要記。這裏沒有考慮cookie的,驗證碼的狀況。

 1 using System;
 2 using System.Collections.Generic;
 3 using System.ComponentModel;
 4 using System.Data;
 5 using System.Drawing;
 6 using System.Linq;
 7 using System.Text;
 8 using System.Threading.Tasks;
 9 using System.Windows.Forms;
10 
11 namespace Wolfy.LoginTest
12 {
13     public partial class LoginForm : Form
14     {
15         public LoginForm()
16         {
17             InitializeComponent();
18         }
19 
20         private void btnLogin_Click(object sender, EventArgs e)
21         {
22             string name = this.txtUserName.Text.Trim();
23             string pwd = this.txtPwd.Text.Trim();
24             StringBuilder sb = new StringBuilder();
25             sb.AppendFormat("name={0}&pwd={1}", name, pwd);
26             Post post = new Post();
27             string result = post.PostLogin("http://localhost:2030/Ashx/Login.ashx", "http://localhost:2030/Login.html", sb.ToString());
28             switch (result)
29             {
30                 case "1":
31                     MessageBox.Show("登陸成功");
32                     break;
33                 case "2":
34                     MessageBox.Show("登陸失敗");
35                     break;
36                 default:
37                     MessageBox.Show("登陸參數錯誤");
38                     break;
39             }
40         }
41 
42         private void btnClose_Click(object sender, EventArgs e)
43         {
44             this.Close();
45         }
46     }
47 }

 

測試結果:根據返回值是1(成功),2(失敗)

源碼下:連接:http://pan.baidu.com/s/1pJ4lFBX 密碼:p6hk

相關文章
相關標籤/搜索