zoukankan      html  css  js  c++  java
  • .NET中HttpWebRequest模拟请求保持登录状态

      最近碰到这样一个需求,ASP项目里需要从另一个API项目的接口中取数据。

      我想了想,最方便也是最快速的方法的就是使用HttpWebRequest请求接口。

      而这里有一个问题,就是API那边接口需要登录之后才能拿到完整的数据。

        未登录价格显示不全:

        由于之前未曾使用过HttpWebRequest,所以并不知道登录完成之后要怎样保持登录状态,进行接下来的请求; 

        花费了我两天时间才研究明白(本人菜鸡,大神轻喷),HttpWebRequest每次请求,服务端是不同的Session, 对于需要登录保持Session才能操作的页面,无法进行。这就要求程序每次请求在同一个Session中。

        服务端每次识别客户端在同一个Session访问,是基于cookie中有SessionID值。每次访问服务端时, 服务端通过识别客户请求的cookie的SessionID值,来判断是否在同一个Session中。 那么就需要在拿列表数据之前,先请求一次登陆接口,然后拿到这次请求的Cookie。 

      HttpWebRequest帮助类:

      1  public class HttpRequest
      2     {
      3         // 保持 Cookie 为同一 Cookie 值。         
      4         protected CookieContainer craboCookie = new CookieContainer();
      5         protected string _Uri = null;         // 标识 Internet 资源的 URI 
      6         protected string _Referer = null;         // 标识 Internet 资源请求的 Referer        
      7         protected string _Headers = null;         // 标识 Internet 资源请求的 Header 
      8         // 标识 Internet 资源请求的 Accept 
      9         protected string _Accept = "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*";
     10         protected List<string> cookiesstrs = null;
     11         protected string cookiesstr = null;
     12         protected CookieCollection cookieheader = null;
     13 
     14         protected string _Method = null;         // 标识 Internet 资源请求的 Method 
     15         protected string _Data = null;         // POST 请求时的数据 
     16         protected string _CharacterSet = null;         // 响应的字符集 
     17         protected HttpStatusCode _StatusCode;         // 响应状态 
     18         protected StringBuilder _Html_Text = new StringBuilder();
     19         public bool IsException = false;
     20         public int TimeOut = 20000;
     21         public HttpRequest(String encode = "GB2312")
     22         {
     23             // 
     24             // TODO: 在此处添加构造函数逻辑 
     25             // 
     26             cookiesstrs = new List<string>();
     27            _CharacterSet = encode;
     28         }
     29         /// <summary> 
     30         /// 对 Internet 资源发起 GET 请求 
     31         /// </summary> 
     32         /// <param name="requestUriString">标识 Internet 资源的URI</param> 
     33         /// <param name="requestReferer">标识 Internet 资源请求的Referer</param> 
     34         public bool OpenRequest(string requestUriString, string requestReferer)
     35         {
     36             _Uri = requestUriString;
     37             _Referer = requestReferer;
     38             _Method = "GET";
     39             return OpenRequest();
     40         }
     41         /// <summary> 
     42         /// 对 Internet 资源发起 GET 请求 
     43         /// </summary> 
     44         /// <param name="requestUriString">标识 Internet资源的URI</param> 
     45         /// <param name="requestReferer">标识 Internet资源请求的Referer</param> 
     46         /// <param name="requestMethod">标识 Internet资源请求的 Post 数据</param> 
     47         public bool OpenRequest(string requestUriString, string requestReferer, string requestData)
     48         {
     49             _Uri = requestUriString;
     50             _Referer = requestReferer;
     51             _Data = requestData;
     52             _Method = "POST";
     53             return OpenRequest();
     54         }
     55         public bool OpenRequestNew(string requestUriString, string requestReferer, string requestData)
     56         {
     57             _Uri = requestUriString;
     58             _Referer = requestReferer;
     59             _Data = requestData;
     60             _Method = "POST";
     61             return OpenRequestNew();
     62         }
     63         public void SetCookieheader(string Cookie)
     64         {
     65 
     66             cookiesstrs.Add(Cookie);
     67              
     68         }
     69       
     70         /// <summary> 
     71         public string GetCookieheader()
     72         {
     73             return cookiesstr;  
     74         }
     75 
     76         public void SetCookie(CookieCollection Cookie)
     77         { 
     78             craboCookie.Add(Cookie);
     79         }
     80         public CookieCollection GetCookie()
     81         {
     82             return cookieheader;
     83         }
     84 
     85         /// 对 Internet 资源发起请求 
     86         /// </summary> 
     87         /// <returns></returns> 
     88         private bool OpenRequest()
     89         {
     90             // 清空已保留代码 
     91             _Html_Text.Remove(0, _Html_Text.Length);
     92             // 创建 HttpWebRequest 实例 
     93             HttpWebRequest Request = (HttpWebRequest)WebRequest.Create(_Uri);
     94             // 设置跟随重定向 
     95             Request.AllowAutoRedirect = true;
     96             #region 判断 Uri 资源类型
     97             {
     98                 Regex _RegexUri = new Regex("^https://", RegexOptions.IgnoreCase);
     99                 if (_RegexUri.IsMatch(_Uri))
    100                     ServicePointManager.CertificatePolicy = new TrustAllCertificatePolicy();
    101             };
    102             #endregion
    103 
    104             //System.Net.WebProxy proxy = new System.Net.WebProxy("172.168.2.254:8080", true);
    105             //proxy.Credentials = new NetworkCredential("linxy", "lxy123456");
    106             //Request.Proxy = proxy;
    107          
    108             Request.Timeout = TimeOut;
    109             Request.Method = _Method;
    110             Request.Accept = _Accept;
    111             Request.UserAgent = "Mozilla/5.0 (X11; U; Linux i686; zh-CN; rv:1.9.1.2) Gecko/20090803 Fedora/3.5.2-2.fc11 Firefox/3.5.2";
    112             Request.Referer = _Referer;
    113             Request.Proxy = null;
    114             Request.CookieContainer = craboCookie;
    115 
    119             if (_Method == "POST")
    120             {
    121                 #region 请求为 POST
    122                 Request.ContentType = "application/x-www-form-urlencoded";
    123               
    124                 byte[] Bytes = Encoding.GetEncoding(_CharacterSet).GetBytes(_Data);
    125                 Request.ContentLength = Bytes.Length;
    126                 using (Stream writer = Request.GetRequestStream())
    127                 {
    128                     writer.Write(Bytes, 0, Bytes.Length);
    129                     writer.Close();
    130                 }
    131                 #endregion
    132             }
    133             #region 读取返回数据
    134             // 设置返回值变量 
    135             bool bResult = true;
    136             try
    137             {
    138                 HttpWebResponse Response = (HttpWebResponse)Request.GetResponse();
    139                 cookiesstr = Response.Headers["Set-Cookie"]?.ToString();
    140                 cookieheader = Request.CookieContainer.GetCookies(new Uri(_Uri));
    141                 // 获取状态值 
    142                 _StatusCode = Response.StatusCode;
    143                 if (_StatusCode == HttpStatusCode.OK)
    144                 {
    145                     
    146                      // 判断页面编码 
    147                     string ContentEncoding = Response.ContentEncoding.ToLower();
    148                     switch (ContentEncoding)
    149                     {
    150                         case "gzip":
    151                            
    152                             break;
    153                         default:
    154                             using (Stream reader = Response.GetResponseStream())
    155                             {
    156                                 StreamReader sr = new StreamReader(reader, Encoding.GetEncoding(CharacterSet));
    157                                 _Html_Text.Append(sr.ReadToEnd());
    158                                 sr.Close();
    159                                 reader.Close();
    160                                 try
    161                                 {
    162                                 _doc.RemoveAll();
    163                                     _doc.LoadXml(_Html_Text.ToString().Trim());
    164                             }
    165                                 catch{}
    166                             }
    167                             break;
    168                     }
    169                  }
    170                 else
    171                     bResult = false;
    172             }
    173             catch (Exception pEx)
    174             {
    175                 IsException = true;
    176                 _Html_Text.Append(pEx.Message);
    177                 return false;
    178             }
    179             #endregion
    180             return bResult;
    181         }
    182         private bool OpenRequestNew()
    183         {
    184             // 清空已保留代码 
    185             _Html_Text.Remove(0, _Html_Text.Length);
    186             // 创建 HttpWebRequest 实例 
    187             HttpWebRequest Request = (HttpWebRequest)WebRequest.Create(_Uri);
    188             // 设置跟随重定向 
    189             Request.AllowAutoRedirect = true;
    190             #region 判断 Uri 资源类型
    191             {
    192                 Regex _RegexUri = new Regex("^https://", RegexOptions.IgnoreCase);
    193                 if (_RegexUri.IsMatch(_Uri))
    194                     ServicePointManager.CertificatePolicy = new TrustAllCertificatePolicy();
    195             };
    196             #endregion
    197 
    198             //System.Net.WebProxy proxy = new System.Net.WebProxy("172.168.2.254:8080", true);
    199             //proxy.Credentials = new NetworkCredential("linxy", "lxy123456");
    200             //Request.Proxy = proxy;
    201 
    202             Request.Timeout = TimeOut;
    203             Request.Method = _Method;
    204             Request.Accept = _Accept;
    205             Request.UserAgent = "Mozilla/5.0 (X11; U; Linux i686; zh-CN; rv:1.9.1.2) Gecko/20090803 Fedora/3.5.2-2.fc11 Firefox/3.5.2";
    206             Request.Referer = _Referer;
    207             Request.Proxy = null;
    208  
    209             foreach (var cookie in cookiesstrs)
    210             {
    211                 Request.Headers.Add("Cookie", cookie);
    212             }
    213            
    214             if (_Method == "POST")
    215             {
    216                 #region 请求为 POST
    217                 Request.ContentType = "application/x-www-form-urlencoded";
    218 
    219                 byte[] Bytes = Encoding.GetEncoding(_CharacterSet).GetBytes(_Data);
    220                 Request.ContentLength = Bytes.Length;
    221                 using (Stream writer = Request.GetRequestStream())
    222                 {
    223                     writer.Write(Bytes, 0, Bytes.Length);
    224                     writer.Close();
    225                 }
    226                 #endregion
    227             }
    228             #region 读取返回数据
    229             // 设置返回值变量 
    230             bool bResult = true;
    231             try
    232             {
    233                 HttpWebResponse Response = (HttpWebResponse)Request.GetResponse();
    234 
    235                 // 获取状态值 
    236                 _StatusCode = Response.StatusCode;
    237                 if (_StatusCode == HttpStatusCode.OK)
    238                 {
    239 
    240                     // 判断页面编码 
    241                     string ContentEncoding = Response.ContentEncoding.ToLower();
    242                     switch (ContentEncoding)
    243                     {
    244                         case "gzip":
    245 
    246                             break;
    247                         default:
    248                             using (Stream reader = Response.GetResponseStream())
    249                             {
    250                                 StreamReader sr = new StreamReader(reader, Encoding.GetEncoding(CharacterSet));
    251                                 _Html_Text.Append(sr.ReadToEnd());
    252                                 sr.Close();
    253                                 reader.Close();
    254                                 try
    255                                 {
    256                                     _doc.RemoveAll();
    257                                     _doc.LoadXml(_Html_Text.ToString().Trim());
    258                                 }
    259                                 catch { }
    260                             }
    261                             break;
    262                     }
    263                     cookiesstr = craboCookie.GetCookieHeader(Request.RequestUri); //把cookies转换成字符串
    264                 }
    265                 else
    266                     bResult = false;
    267             }
    268             catch (Exception pEx)
    269             {
    270                 IsException = true;
    271                 _Html_Text.Append(pEx.Message);
    272                 return false;
    273             }
    274             #endregion
    275             return bResult;
    276         }
    277         private XmlDocument _doc = new XmlDocument();
    278 
    279         public XmlDocument Doc
    280         {
    281             get
    282             {
    283                 return _doc;
    284             }
    285         }
    286         
    287 
    288         /// <summary> 
    289         /// 获取或设置 Uri 资源字符集 
    290         /// </summary> 
    291         public string CharacterSet
    292         {
    293             get
    294             {
    295                 return _CharacterSet;
    296             }
    297             set
    298             {
    299                 _CharacterSet = value;
    300             }
    301         }
    302         /// <summary> 
    303         /// 获取或设置 Uri 资源标识 
    304         /// </summary> 
    305         public string RequestUriString
    306         {
    307             get
    308             {
    309                 return _Uri;
    310             }
    311             set
    312             {
    313                 _Uri = value;
    314             }
    315         }
    316         /// <summary> 
    317         /// 获取或设置 Uri 资源请求 Accept 
    318         /// </summary> 
    319         public string Accept
    320         {
    321             get
    322             {
    323                 return _Accept;
    324             }
    325             set
    326             {
    327                 _Accept = value;
    328             }
    329         }
    330         public string HtmlDocument
    331         {
    332             get
    333             {
    334                 return _Html_Text.ToString();
    335             }
    336         }
    337 
    338         
    339     }

      HttpWebrequest设置cookie可以用 以下两种方式:

    • Request.CookieContainer = craboCookie;
    • Request.Headers.Add("Cookie", cookie);

      调用方法:

      HttpRequest hr = new  HttpRequest("UTF-8");
      string strUrl = APIUrl + "/IAccount/Login";
      string strUrlPan = string.Format("customerID={0}&md5Pwd={1}&loginType={2}&source={3}", txtUid.Text.Trim(), Util.GetMD5(txtPwd.Text.Trim()), 1, 3);
      hr.OpenRequest(strUrl + "?" + strUrlPan, "");
      //缓存登录Cookie
      Session["Cookieheader"] = hr.GetCookie(); 
      var rb = Newtonsoft.Json.JsonConvert.DeserializeObject<LoginResponseData>(hr.HtmlDocument.Trim());
      //保存站点
      CookieUtil.ClearCookie("ChangeWebSiteSysNo");
      CookieUtil.SetCookie("ChangeWebSiteSysNo", rb.data.CustomerInfo.WebSiteSysNo.ToString());
      //保存登录用户标识
      string cookiestr = hr.GetCookieheader();
      string str = getCookie(cookiestr, "path=/,userGuid").Replace("path=/,", "");
      var cookieArr = str.Split('=');
      CookieUtil.ClearCookie("userGuid");
      CookieUtil.SetCookie("userGuid", cookieArr.Length > 0 ? cookieArr[1] : "");

    这里有一个比较坑的就是,因为我那边API项目不仅要验证是否登录还要验证用户唯一标识,所以我这里将userGuid也缓存了起来在下一次请求时一并传过去。

    然后再另起一个请求拿数据

    //设置请求登录Cookie
    Icson.Utils.HttpRequest hr1 = new Icson.Utils.HttpRequest("UTF-8");
    System.Net.CookieCollection Cookies = new System.Net.CookieCollection();
    if (Session["Cookieheader"] != null)
      Cookies.Add((System.Net.CookieCollection)Session["Cookieheader"]);
    Cookies.Add(new System.Net.Cookie("userGuid", CookieUtil.GetCookie("userGuid"), "/", APIUrl.Replace("http://", "")));
    hr1.SetCookie(Cookies);
    //请求商品列表
    string strUrl = APIUrl + "/IProductList/ListNew";
    string strUrlPan = string.Format("c1SysNo={0}&c2SysNo={1}&c3SysNo={2}&extCode={3}&filter={4}&limit=30&madeIn=-1&offset={5}&query={6}&sType=1&sort=8&source=3&systemversion=9&version=3.2.2", ddlC1.SelectedItem?.Value.TryInt() < 0 ? "" : ddlC1.SelectedItem?.Value, ddlC2.SelectedItem?.Value.TryInt() < 0 ? "" : ddlC2.SelectedItem?.Value, "", 0, "", 0, txtProductName.Text.Trim());
    hr1.OpenRequest(strUrl + "?" + strUrlPan, "", "");

    这样就可以拿到完整的列表数据了

    以上就是一次HttpWebRequest踩坑经历,希望各位遇到能够避免在这上面浪费过多时间。

     

  • 相关阅读:
    爬虫第二弹之http协议和https协议
    爬虫第一弹之py爬虫的相关概念
    Flask第十四篇- Flask-Session组件、WTForms组件、数据库连接池(POOL)
    Flask第十三篇- flask请求上下文源码解读、http聊天室单聊/群聊(基于gevent-websocket)
    Flask第十二篇- flask中的CBV、werkzeug+上下文初步解读、偏函数和线程安全
    Flask第十一篇装饰器的坑及解决办法、flask中的路由/实例化配置/对象配置/蓝图/特殊装饰器(中间件、重定义错误页面)
    Flask第十八篇 Flask-Migrate
    Flask第十七篇 Flask-Scrip
    Flask第十六篇 Flask-SQLAlchemy
    Flask第十篇 before_request after_request
  • 原文地址:https://www.cnblogs.com/AlexZha/p/13691557.html
Copyright © 2011-2022 走看看