通过C#登录网站


81

我使用C#相对较新,并且有一个应用程序可以读取网站上部分源代码。一切正常;但是问题在于相关页面需要用户登录才能访问此源代码。我的程序需要一种将用户最初登录到网站的方法-完成之后,我将能够访问和阅读源代码。

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

我整天都在搜索有关此操作的方法,并尝试了一些示例,但是没有运气。

提前致谢


因此,我可以想到许多方法来实现……C#程序是否直接通过HTTP从服务器请求“代码”,还是您将浏览器应用程序带回了?需要更多信息。
米奇·贝克

该程序使用WebClient.DownloadString(“ URL”)

Answers:


112

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

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


发布到登录表单

表单帖子易于模拟,这只是格式化帖子数据的一种情况,如下所示:

field1=value1&field2=value2

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

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"];

这是您应该在登录表单的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=-

在登录表单后面获取页面

现在,您可以对需要登录的页面执行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();
}

编辑:

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

using (StreamReader sr = new StreamReader(resp.GetResponseStream()))
{
    pageSource = sr.ReadToEnd();
}

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


非常感谢您的详细答复;但仍有一部分我不确定。我是否应该更改有关您发布的“ Set -cookie”,“ Cookie”或“ PHPSESSID”的内容?我尝试在输入信息的程序中简单地使用该代码,但似乎并没有登录(我想我正在用cookie搞砸了)。

该代码应可以使用逐字记录。服务器设置Cookie(在Set-cookie中),而客户端(即您)将cookie发送回备份为Cookie)。首先要检查的是第一个POST实际上已登录,您可能会发现服务器在POST表单中期望有另一个字段(听起来很奇怪,有时您需要一个带有按钮名称的空字段)。我已经更新了帖子,以显示如何查看POST的结果。
马特·布林德里

我不确定我第一次做错了什么,但是现在可以了!非常感谢您的帮助。

1
如何确定用户是否成功通过身份验证?
Cyral 2012年

2
我知道我们不应该在这里表​​达谢意,但伙计,您救了我的屁股!+1
欧文·詹姆斯

39

通过创建一个从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");

调试时,(使其公开)cookie始终为空。该网站肯定会在我正在下载的页面上发出cookie。
C4d

谢谢,经过数小时的查找解决方案,此方法有效!
Essej

9

Matthew Brindley,您的代码对于我需要的某些网站(登录)非常有效,但是我需要更改为HttpWebRequestHttpWebResponse否则我从远程服务器收到404错误请求。此外,我想用您的代码来分享我的解决办法,而且是我它试图登录到基于Moodle的网站,但它并没有在你的工作一步“获取页面的登录表单后面”,因为当成功POST操作的登录后,'Set-Cookie'尽管其他网站也没有返回任何标题。

因此,我认为这是我们需要为下一个请求存储Cookie的地方,因此我添加了此内容。


对于“ POST到登录表单”代码块:

var cookies = new CookieContainer();
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(formUrl);
req.CookieContainer = cookies;


然后到“获取登录表单后面的页面”:

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


这样做,让我登录并获取“登录后页面”(基于网站的心情)的源代码,我知道这是对CookieContainer和HTTPCookies的模糊用法,因为我们可能会首先询问是否存在之前保存的一组cookie。将请求发送到服务器。这个作品没有问题,无论如何,但这里有一个很好的信息,以了解WebRequestWebResponse使用示例项目和教程:
检索HTTP内容.NET
在.NET中如何使用HttpWebRequest和HttpWebResponse


2

有时,它可能有助于关闭AllowAutoRedirect并设置登录POST和页面GET请求使用同一用户代理。

request.UserAgent = userAgent;
request.AllowAutoRedirect = false;
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.