【问题标题】:Using WebClient or WebRequest to login to a website and access data使用 WebClient 或 WebRequest 登录网站并访问数据
【发布时间】:2023-10-10 01:48:01
【问题描述】:

我正在尝试使用 WebClient/WebRequest 访问网站上的受限数据。该网站没有官方 API,所以我要做的只是填写 HTML 表单并将值发布到服务器,所以我已经登录了。

我尝试了thisthis,但似乎未登录即将到来的请求。

后一个例子更有吸引力,因为我显然更喜欢WebClient,但旧版WebRequest 可以。

无论如何,在第一个示例中,我认为它确实登录了,但即将到来的访问私有数据的请求会返回一个页面,其中包含“这是仅限会员的内容”的消息。

如何让WebClient永久登录?

【问题讨论】:

标签: c# login webclient forms webrequest


【解决方案1】:

更新:

请参阅下面的my comment


这就是我所做的并且它有效 (credit)。

先添加这个类:

namespace System.Net
{
  using System.Collections.Specialized;
  using System.Linq;
  using System.Text;

  public class CookieAwareWebClient : WebClient
  {
    public void Login(string loginPageAddress, NameValueCollection loginData)
    {
      CookieContainer container;

      var request = (HttpWebRequest)WebRequest.Create(loginPageAddress);

      request.Method = "POST";
      request.ContentType = "application/x-www-form-urlencoded";

      var query = string.Join("&", 
        loginData.Cast<string>().Select(key => $"{key}={loginData[key]}"));

      var buffer = Encoding.ASCII.GetBytes(query);
      request.ContentLength = buffer.Length;
      var requestStream = request.GetRequestStream();
      requestStream.Write(buffer, 0, buffer.Length);
      requestStream.Close();

      container = request.CookieContainer = new CookieContainer();

      var response = request.GetResponse();
      response.Close();
      CookieContainer = container;
    }

    public CookieAwareWebClient(CookieContainer container)
    {
      CookieContainer = container;
    }

    public CookieAwareWebClient()
      : this(new CookieContainer())
    { }

    public CookieContainer CookieContainer { get; private set; }

    protected override WebRequest GetWebRequest(Uri address)
    {
      var request = (HttpWebRequest)base.GetWebRequest(address);
      request.CookieContainer = CookieContainer;
      return request;
    }
  }
}

用法:

public static void Main()
{
  var loginAddress = "www.mywebsite.com/login";
  var loginData = new NameValueCollection
    {
      { "username", "shimmy" },
      { "password", "mypassword" }
    };

  var client = new CookieAwareWebClient();
  client.Login(loginAddress, loginData);
}

【讨论】:

  • @Anthony,如果您遇到非静态上下文问题,请使用 System.Text.Encoding 而不是 Encoding。
  • 你不能 loginData.ToString(),它只是类型名称。
  • 它曾经工作过。无论如何,伙计们,你可以使用 FormUrlEncodedContent 然后 ReadAsStringAsync 代替。无论如何,这个答案在发布时很有用,我建议改用HttpClient,提供一个覆盖SendAsyncDelegatingHandler 来登录。我希望能抽出时间来刷新答案。
  • 无论如何我已经编辑了我的答案,我希望它现在可以工作。不要忘记,这是一个开放的网站,而不是投反对票和生气,您可以编辑我的答案,以回报社区和其他人在未来查看此答案。
  • @Shimmy 这对我不起作用,因为服务器总是返回 200 ok 代码,但是使用 this answer 我可以检查容器是否包含正确站点的名为 .ASPXAUTH 的 cookie,它做的工作
【解决方案2】:

HTTP 是无状态的。所以,WebClient 不能永久登录。HTTP 中不存在会话的概念。 ASP.NET 等服务器端技术通过会话概念模拟有状态行为,该概念使用 cookie 或在每个请求中来回发送的查询字符串参数。话虽如此,可以从 WebClient 模拟浏览器所做的事情。如果您有权访问该网站,请使用正确的凭据连接到该网站并使用 Fiddler 捕获流量。然后,确保 WebClient 发出与浏览器完全相同的 cookie、请求标头、查询字符串等。

【讨论】: