zoukankan      html  css  js  c++  java
  • Winform模拟post请求和get请求登录网站

    引言

    最近有朋友问如何用winform模拟post请求,然后登录网站,稍微想了一下,大致就是对http报文的相关信息的封装,然后请求网站登录地址的样子。发现自己的博客中对这部分只是也没总结,就借着这股风,总结一下http报文的相关知识吧。

    HTTP定义

    超文本传输协议 (HTTP-Hypertext transfer protocol) 是一种详细规定了浏览器和万维网服务器之间互相通信的规则,通过因特网传送万维网文档的数据传送协议。

     这里对http的具体内容就不再介绍了,主要分析http报文信息。

    http报文分为:请求报文和响应报文。

    HTTP请求报文

    一个Http请求报文由请求行(request line)、请求头部(header)、空行和请求数据4个部分组成,请求报文个格式如下:

    Post请求

    弄一个简单的登录页面,使用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 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:这是最重要的请求头信息之一。

        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的,验证码的情况。

     LoginForm

    测试结果:根据返回值是1(成功),2(失败)

    源码下,猛戳这里:链接:http://pan.baidu.com/s/1pJ4lFBX 密码:p6hk

  • 相关阅读:
    Mybatis框架学习_6_mapper.xml 文件中的输入参数详解 (paraterType)
    Mybatis框架学习_5_自定义类型转换器
    Mybatis框架学习_4_属性文件、全局参数、别名
    Mybatis框架学习_3_基于约定或动态代理实现增删改查
    Mybatis框架学习_2_增删改查的简单实现
    Mybatis框架学习_1_简介以及入门示例
    Linux 系统下启动命名的书写过程
    spring-boot-Web学习2-模板引擎 Thymeleaf
    spring-boot-Web学习1-简介
    MacBook无法开机问题
  • 原文地址:https://www.cnblogs.com/lyl6796910/p/3722280.html
Copyright © 2011-2022 走看看