zoukankan      html  css  js  c++  java
  • 使用HttpWebRequest模拟登陆阿里巴巴(alibaba、httpwebrequest、login)

    前言

      其实老喜欢取经,偶尔也得分享下。关于阿里巴巴国际站的登陆,过程有点复杂但是算不上难。一不小心少个东西倒也挺麻烦的。

      主要是看下请求类HttpClient基本请求封装使用,AliClient模拟浏览器的操作与数据封装

      这里只是简单说一下主要的类和注意点,主要步骤与注意点都写在代码注释里了。项目源码下载地址:http://git.oschina.net/GspringG/AliLogin

    正文

    1. 主要类/方法

    • HttpClient请求模拟的基础类,也就那么个过程http header设置一下,然后模拟就行了.需要注意的地方在代码注释里
      using System;
      using System.Drawing;
      using System.IO;
      using System.Net;
      using System.Net.Security;
      using System.Security.Cryptography.X509Certificates;
      using System.Text;
      
      namespace Main.Http
      {
          public class HttpClient
          {
              const string Accept = "text/html, application/xhtml+xml, */*";
              public const string UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko";
              const int Timeout = 15000;//超时时间,但前提是请求允许超时才行。
              const string AcceptLanguage = "Accept-Language:zh-CN";
              const string AcceptEncoding = "Accept-Encoding:gzip, deflate";
              const string Contenttype = "application/x-www-form-urlencoded";
              /// <summary>
              /// 静态构造方法
              /// </summary>
              static HttpClient()
              {
                  //伪造证书,验证服务器证书回调自动验证
                  ServicePointManager.ServerCertificateValidationCallback = CheckValidationResult;
                  //客户端系统 win7或者winxp上可能会出现 could not create ssl/tls secure channel的问题导致加载ali登陆验证码报错
                  //这里必须设置
                  ServicePointManager.Expect100Continue = false;//默认是true,要手动设为false 
                  ServicePointManager.SecurityProtocol=SecurityProtocolType.Ssl3;
      
                  ServicePointManager.DefaultConnectionLimit = 1000;
              }
      
              public static string Get(string url, CookieContainer cookie, int retryCount = 3)
              {
                  return Request(url, cookie, "GET", null, retryCount);
              }
              public static string Post(string url, CookieContainer cookie, string postData, int retryCount = 3)
              {
                  return Request(url, cookie, "POST", postData, retryCount);
              }
      
              public static string Post(string url, CookieContainer cookie, string postData, Action<HttpWebRequest> beginRequest, int reTry = 0)
              {
                  return Request(url, cookie, "POST", postData, reTry, beginRequest);
              }
      
              private static string Request(string url, CookieContainer cookie, string method, string postData, int retryCount, Action<HttpWebRequest> beginRequest = null)
              {
                  string html = string.Empty;
                  for (var i = 0; i <= retryCount; i++)
                  {
                      try
                      {
                          html = Request(url, cookie, method, postData, beginRequest);
                          return html;
                      }
                      catch (Exception e)
                      {
                          if (i == retryCount)
                          {
                              throw new Exception(e.ToString());
                          }
                      }
                  }
                  return html;
              }
      
              public static bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
              {   // 伪造证书,总是接受  
                  return true;
              }
      
              private static string Request(string url, CookieContainer cookie, string method, string postData, Action<HttpWebRequest> beginRequestHandle = null)
              {
                  var request = (HttpWebRequest)WebRequest.Create(url);
                  request.Method = method;
                  request.CookieContainer = cookie;
                  request.AllowAutoRedirect = true;
                  request.ContentType = Contenttype;
                  request.Accept = Accept;
                  request.Timeout = Timeout;
                  request.UserAgent = UserAgent;
                  request.Headers.Add(AcceptLanguage);
                  request.Headers.Add(AcceptEncoding);
      
                  request.AutomaticDecompression = DecompressionMethods.GZip;
      
                  if (beginRequestHandle != null)
                      beginRequestHandle(request);
      
                  if (!string.IsNullOrEmpty(postData))
                  {
                      byte[] byteRequest = Encoding.UTF8.GetBytes(postData);
                      request.ContentLength = byteRequest.Length;
                      var stream = request.GetRequestStream();
                      stream.Write(byteRequest, 0, byteRequest.Length);
                      stream.Close();
                  }
                  var httpWebResponse = (HttpWebResponse)request.GetResponse();
      
                  var responseStream = httpWebResponse.GetResponseStream();
                  if (responseStream == null) return string.Empty;
                  if (responseStream.CanTimeout)
                  {
                      responseStream.ReadTimeout = 15000;
                  }
                  var encoding = Encoding.GetEncoding(httpWebResponse.CharacterSet ?? "UTF8");
      
                  var streamReader = new StreamReader(responseStream, encoding);
      
                  string html = streamReader.ReadToEnd();
                  streamReader.Close();
                  responseStream.Close();
                  request.Abort();
                  httpWebResponse.Close();
                  return html;
              }
      
              public static byte[] DownloadFile(string url, CookieContainer cookie)
              {
                  var webClient = new CookieWebClient { Cookie = cookie };
                  byte[] data = webClient.DownloadData(url);
                  return data;
              }
              public static Image DownloadImage(string url, CookieContainer cookie)
              {
                  byte[] data = DownloadFile(url, cookie);
                  var ms = new MemoryStream(data);
                  var image = Image.FromStream(ms);
                  ms.Close();
                  return image;
              }
          }
      }
      View Code
    • AliClient:相当于一个浏览器,存储着cookie、session、_csrf_token_、userName等信息。客户端发出的模拟请求都通过AliClient发出保证全部在一个会话中。(想想一个浏览器需要些什么,浏览器是怎么做的。就感觉很合理了)
      using System;
      using System.Collections.Specialized;
      using System.Net;
      using System.Web;
      using Main.Http;
      
      namespace Main.Ali
      {
          public class AliClient
          {
              const string _csrf_token_ = "_csrf_token_";
              public CookieContainer Cookie { get; set; }
              public string SessionId { get; set; }
      
              public string CsrfToken { get; set; }
              public AliLoginUser AliLoginUser { get; set; }
              public string DmtrackPageid { get; set; }
              public string UserName
              {
                  get
                  {
                      if (AliLoginUser == null) return null;
                      if (AliLoginUser.person_data == null) return null;
                      return AliLoginUser.person_data.login_id;
                  }
              }
              public AliClient()
              {
                  Cookie = new CookieContainer();
              }
              public string Get(string url)
              {
                  return HttpClient.Get(AddCsrfTokenToUrl(url), this.Cookie, 3);
              }
              public string Post(string url, string postData)
              {
                  return HttpClient.Post(AddCsrfTokenToUrl(url), this.Cookie, AddCsrfTokenToPostData(postData), 3);
              }
              //post请求时不用手动加了,默认都加上
              private string AddCsrfTokenToPostData(string postData)
              {
                  NameValueCollection queryString = HttpUtility.ParseQueryString(postData);
                  if (queryString[_csrf_token_] == null)
                  {
                      queryString.Add("_csrf_token_", this.CsrfToken);
                  }
                  return queryString.ToString();
              }
              //Get请求时不用手动加了,默认都加上
              private string AddCsrfTokenToUrl(string url)
              {
      
                  if (string.IsNullOrWhiteSpace(this.CsrfToken)) return url;
                  UriBuilder ub = new UriBuilder(url);
                  NameValueCollection queryString = HttpUtility.ParseQueryString(ub.Query);
                  if (queryString[_csrf_token_] == null)
                  {
                      queryString.Add("_csrf_token_", this.CsrfToken);
                  }
                  ub.Query = queryString.ToString();
                  string newurl = ub.Uri.ToString();
                  return newurl;
              }
      
          }
      }
      View Code
    • AliPassporter:阿里巴巴登陆核心类(具体个注意细节点都在代码内部已注释)

        登陆过程为:从上到下依次

          1.PrepareLogin:

    1         /// <summary>
    2         /// 登陆前先请求一下页面获取sessionId,DmtrackPageid,初始化cookie的值,像正常访问浏览器一样
    3         /// </summary>
    4         /// <param name="aliClient"> AliClient当需要多账号登陆时,每个账号的cookie 各种验证id等独有的东西放到各自的Client中,相当于每个独立的浏览器</param>
    5         /// <param name="isSpec">针对某种特殊情况取值方法不一样,默认false</param>
    6         public static void PrepareLogin(AliClient aliClient, bool isSpec = false);

          2.DoLoginStep1:

    1        /// <summary>
    2         ///     登录阿里巴巴
    3         /// </summary>
    4         /// <param name="aliClient"> AliClient当需要多账号登陆时,每个账号的cookie 各种验证id等独有的东西放到各自的Client中</param>
    5         /// <param name="account">帐户名</param>
    6         /// <param name="password">密码</param>
    7         /// <param name="checkCode">验证码</param>
    8         /// <returns>登陆结果(true/false)</returns>
    9         public static bool DoLoginStep1(AliClient aliClient, string account, string password, string checkCode);

          3.DoLoginStep2:

     1         /// <summary>
     2         ///     登录处理第二步
     3         /// </summary>
     4         /// <param name="aliClient"></param>
     5         /// <param name="userId">账户</param>
     6         /// <param name="password">密码</param>
     7         /// <param name="dmtrackPageid">令牌1</param>
     8         /// <param name="st">令牌三</param>
     9         /// <returns>登陆结果</returns>
    10         private static bool DoLoginStep2(AliClient aliClient, string userId, string password, string dmtrackPageid, string st);

          4.DoCheckCode:

    1         /// <summary>
    2         /// 获取checkcode,图片验证码,其实有时候是不需要的。可以先判断一下,不行再获取验证码
    3         /// </summary>
    4         /// <param name="aliClient">aliClient</param>
    5         /// <returns>验证码图片,如果是web应用,直接把checkCodeUrl(img src=checkCodeUrl)写进去就行了</returns>
    6         public static Image DoCheckCode(AliClient aliClient);

          5.登陆过程中还会调用GetToken、GetSt、GetCsrfToken等方法提供登录所需要的get/post参数

          6.前端调用流程:登录过程关键代码(详情参见详细代码)

               //1.初始化_aliClient,相当于打开一个浏览器,并设置一个空的cookie
               AliClient  _aliClient=new AliClient {Cookie = new CookieContainer()};
               //2.无需验证码登陆时这里替换为PrepareLogin(_aliClient);
               RefreshCheckCode();
               //3.登陆系统,异步方法防止页面假死
               var data=await AliPassporter.DoLoginAsync(_aliClient, UserName, Password, CheckCode);
               if (data)
                {
                    //登陆成功,登陆后其他数据就随便抓了,这里要注意,需要手机验证码的,要在网页中先把手机验证码输入了
                    //我的测试账号默认写在里面,别乱玩就行了
                    //进入管理个人信息页面
                    var html = _aliClient.Get("http://accounts.alibaba.com/user/organization/manage_person_profile.htm");
                    MessageBox.Show("登陆成功!");
                    //_aliClient.Post("");
                }
                else
                {
                    MessageBox.Show("登陆失败!");
                }            

     总结

      以上就是阿里巴巴国际站登陆的全部过程,总体大同小异,很久之前写的了(建议先把注释看一遍再用)。现在拿出来分享一下,顺便复习一下HttpWebRequest的相关使用。

    ——我认识一个人,他每做一件小事都像救命稻草一样抓着。有一天我发现,豁!他抱着的已经是让我仰望的参天大树了.
  • 相关阅读:
    Dojo(发音:豆粥)的目标是解决DHTML应用程序长期存在的历史问题
    如何用Fireworks制作图标的透明效果
    2021.09.15膜你赛
    2021.09.14 膜你赛
    2021.08.29 膜你赛
    2021.08.28 膜你赛
    2021.10.06 膜你赛
    2021.09.18 膜你赛
    2021.09.13膜你赛
    2021.10.05膜你赛
  • 原文地址:https://www.cnblogs.com/SpringRen/p/AliLogin.html
Copyright © 2011-2022 走看看