通过C#登录网站

73 c# webclient httpwebrequest

我对使用C#比较陌生,并且有一个应用程序可以在网站上读取部分源代码.这一切都有效; 但问题是有问题的页面要求用户登录才能访问此源代码.我的程序需要一种最初将用户登录到网站的方式 - 完成后,我将能够访问和阅读源代码.

需要登录的网站是:mmoinn.com/index.do?PageModule=UsersLogin

我一整天都在寻找关于如何做到这一点并尝试过的例子,但没有运气.

提前致谢

Mat*_*ley 106

您可以继续使用WebClient进行POST(而不是GET,这是您当前使用的DownloadString 的HTTP动词),但我认为您会发现使用(稍微)较低级别的WebRequest和WebResponse类更容易.

这有两个部分 - 第一部分是发布登录表单,第二部分是恢复"Set-cookie"标题,并将其作为"Cookie"发送回服务器以及您的GET请求.从现在开始,服务器将使用此cookie来识别您(假设它使用基于cookie的身份验证,我非常有信心,因为该页面返回包含"PHPSESSID"的Set-cookie标头).


发布到登录表单

表单帖子很容易模拟,只是格式化您的帖子数据的情况如下:

field1=value1&field2=value2
Run Code Online (Sandbox Code Playgroud)

使用我改编自Scott Hanselman的 WebRequest和代码,以下是将表单数据发布到登录表单的方式:

string formUrl = "http://www.mmoinn.com/index.do?PageModule=UsersAction&Action=UsersLogin"; // NOTE: This is the URL the form POSTs to, not the URL of the form (you can find this in the "action" attribute of the HTML's form tag
string formParams = string.Format("email_address={0}&password={1}", "your email", "your password");
string cookieHeader;
WebRequest req = WebRequest.Create(formUrl);
req.ContentType = "application/x-www-form-urlencoded";
req.Method = "POST";
byte[] bytes = Encoding.ASCII.GetBytes(formParams);
req.ContentLength = bytes.Length;
using (Stream os = req.GetRequestStream())
{
    os.Write(bytes, 0, bytes.Length);
}
WebResponse resp = req.GetResponse();
cookieHeader = resp.Headers["Set-cookie"];
Run Code Online (Sandbox Code Playgroud)

以下是您应在登录表单的Set-cookie标头中看到的示例:

PHPSESSID=c4812cffcf2c45e0357a5a93c137642e; path=/; domain=.mmoinn.com,wowmine_referer=directenter; path=/; domain=.mmoinn.com,lang=en; path=/;domain=.mmoinn.com,adt_usertype=other,adt_host=-
Run Code Online (Sandbox Code Playgroud)

获取登录表单后面的页面

现在,您可以对需要登录的页面执行GET请求.

string pageSource;
string getUrl = "the url of the page behind the login";
WebRequest getRequest = WebRequest.Create(getUrl);
getRequest.Headers.Add("Cookie", cookieHeader);
WebResponse getResponse = getRequest.GetResponse();
using (StreamReader sr = new StreamReader(getResponse.GetResponseStream()))
{
    pageSource = sr.ReadToEnd();
}
Run Code Online (Sandbox Code Playgroud)

编辑:

如果需要查看第一个POST的结果,可以恢复它返回的HTML:

using (StreamReader sr = new StreamReader(resp.GetResponseStream()))
{
    pageSource = sr.ReadToEnd();
}
Run Code Online (Sandbox Code Playgroud)

将其直接放在下面cookieHeader = resp.Headers["Set-cookie"];,然后检查pageSource中保存的字符串.

  • 我知道我们不应该在这里表​​示感谢,但伙计,你救了我的屁股!+1 (2认同)

Jos*_*osh 35

您可以通过创建一个派生自WebClient的类,重写其GetWebRequest方法并在其上设置CookieContainer对象来简化操作.如果您始终设置相同的CookieContainer实例,则将自动为您处理cookie管理.

但是在发送之前获取HttpWebRequest的唯一方法是从WebClient继承并覆盖该方法.

public class CookieAwareWebClient : WebClient
{
    private CookieContainer cookie = new CookieContainer();

    protected override WebRequest GetWebRequest(Uri address)
    {
        WebRequest request = base.GetWebRequest(address);
        if (request is HttpWebRequest)
        {
            (request as HttpWebRequest).CookieContainer = cookie;
        }
        return request;
    }
}

var client = new CookieAwareWebClient();
client.BaseAddress = @"https://www.site.com/any/base/url/";
var loginData = new NameValueCollection();
loginData.Add("login", "YourLogin");
loginData.Add("password", "YourPassword");
client.UploadValues("login.php", "POST", loginData);

//Now you are logged in and can request pages    
string htmlSource = client.DownloadString("index.php");
Run Code Online (Sandbox Code Playgroud)


Why*_*ous 8

Matthew Brindley,你的代码非常适合我需要的一些网站(登录),但是我需要更改为HttpWebRequest,HttpWebResponse否则我从远程服务器收到404 Bad Request.此外,我想用您的代码来分享我的解决办法,而且是我试过登录到一个基于Moodle的网站,但它并没有在你的工作一步" 获取页面的登录表单后面 ",因为当成功POST操作的登录时,'Set-Cookie'尽管有其他网站,Header 也没有返回任何内容.

所以我认为我们需要为下一个请求存储cookie,所以我添加了这个.


到" POST到登录表单 "代码块:

var cookies = new CookieContainer();
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(formUrl);
req.CookieContainer = cookies;
Run Code Online (Sandbox Code Playgroud)


并且到" 获取登录表单后面的页面 ":

HttpWebRequest getRequest = (HttpWebRequest)WebRequest.Create(getUrl);
getRequest.CookieContainer = new CookieContainer();
getRequest.CookieContainer.Add(resp.Cookies);
getRequest.Headers.Add("Cookie", cookieHeader);
Run Code Online (Sandbox Code Playgroud)


这样做,让我登录并获取"登录页面"的源代码(基于网站的moodle)我知道这是对CookieContainerHTTPCookies 的模糊使用,因为我们可能先问一下以前是否保存了以前的cookie集将请求发送到服务器.无论如何这都没有问题,但是这里有一个很好的信息,可以阅读WebRequestWebResponse使用示例项目和教程:
在.NET中检索HTTP内容如何在.NET
中使用HttpWebRequest和HttpWebResponse