我对使用 C# 比较陌生,并且有一个可以读取网站上部分源代码的应用程序。一切正常;但问题是有问题的页面需要用户登录才能访问此源代码。我的程序需要一种方法来初始将用户登录到网站 - 完成之后,我将能够访问和阅读源代码。
需要登录的网站是:mmoinn.com/index.do?PageModule=UsersLogin
我已经搜索了一整天关于如何执行此操作并尝试了示例,但没有运气。
提前致谢
我对使用 C# 比较陌生,并且有一个可以读取网站上部分源代码的应用程序。一切正常;但问题是有问题的页面需要用户登录才能访问此源代码。我的程序需要一种方法来初始将用户登录到网站 - 完成之后,我将能够访问和阅读源代码。
需要登录的网站是:mmoinn.com/index.do?PageModule=UsersLogin
我已经搜索了一整天关于如何执行此操作并尝试了示例,但没有运气。
提前致谢
您可以继续使用 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 中保存的字符串。
您可以通过创建一个派生自 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");
Matthew Brindley,您的代码对于我需要的某些网站(需要登录)非常有效,但我需要更改为HttpWebRequest,HttpWebResponse否则我会从远程服务器收到404 Bad Request 。另外,我想使用您的代码分享我的解决方法,并且我尝试使用它登录到基于 moodle 的网站,但在您的步骤“获取登录表单后面的页面”时它不起作用,因为当成功发布登录,尽管其他网站有,但标题'Set-Cookie'没有返回任何内容。
所以我认为这是我们需要为下一个请求存储 cookie 的地方,所以我添加了这个。
到“ POSTing to the login form ”代码块:
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并获取“登录后页面”的源代码(基于网站的moodle)将请求发送到服务器。无论如何,这都没有问题,但这里有一个很好的信息可供阅读WebRequest以及WebResponse示例项目和教程:
Retrieving HTTP content in .NET
How to use HttpWebRequest and HttpWebResponse in .NET
有时,它可能有助于关闭AllowAutoRedirect和设置登录POST和页面GET请求相同的用户代理。
request.UserAgent = userAgent;
request.AllowAutoRedirect = false;