Подтвердить что ты не робот

Войдите на сайт, через С#

Я относительно новичок в использовании С# и имею приложение, которое читает части исходного кода на веб-сайте. Это все работает; но проблема заключается в том, что на запрашиваемой странице пользователь должен войти в систему, чтобы получить доступ к этому исходному коду. Что моя программа нуждается в способе изначально зарегистрировать пользователя на веб-сайте - после этого я смогу получить доступ и прочитать исходный код.

Веб-сайт, на который нужно войти, является: mmoinn.com/index.do?PageModule=UsersLogin

Я искал весь день о том, как это сделать, и пробовал примеры, но не повезло.

Заранее спасибо

4b9b3361

Ответ 1

Вы можете продолжать использовать WebClient для POST (вместо GET, который является HTTP-глаголом, который вы используете с DownloadString), но я подумайте, что вам будет легче работать с (слегка) низкоуровневыми классами WebRequest и WebResponse.

Для этого есть две части: первая заключается в том, чтобы опубликовать форму входа, вторая восстанавливает заголовок "Set-cookie" и отправляет его обратно на сервер как "Cookie" вместе с вашим запросом GET. Сервер будет использовать этот файл cookie, чтобы идентифицировать вас с этого момента (при условии, что он использует аутентификацию на основе файлов cookie, и я уверен, что именно эта страница возвращает заголовок Set-cookie, который включает в себя "PHPSESSID" ).


POSTing в форме входа

Формы сообщений легко имитировать, это всего лишь случай форматирования ваших данных сообщения следующим образом:

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 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();
}

EDIT:

Если вам нужно просмотреть результаты первого POST, вы можете восстановить HTML-код, который он вернул, с помощью

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

Поместите это непосредственно ниже cookieHeader = resp.Headers["Set-cookie"];, а затем проверите строку, содержащуюся в файле pageSource.

Ответ 2

Вы можете немного упростить ситуацию, создав класс, который происходит из 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");

Ответ 3

Мэтью Бриндли, ваш код работал очень хорошо на каком-то веб-сайте, который мне нужен (с логином), но мне нужно было перейти на HttpWebRequest и HttpWebResponse, в противном случае я получить 404 Bad Request с удаленного сервера. Кроме того, я хотел бы поделиться своим обходным путем с помощью вашего кода и что я попробовал его войти на сайт на основе moodle, но он не работал на вашем шаге " ПОЛУЧЕНИЕ страницы за формой входа", потому что, когда он успешно выполнил вход в систему, заголовок 'Set-Cookie' ничего не возвращал, несмотря на то, что другие сайты делают это.

Итак, я думаю, что нам нужно хранить куки для следующих запросов, поэтому я добавил это.


К коду POSTing к форме входа в систему:

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);


Сделав это, позвольте мне войти в систему и получить исходный код "страницы за логином" (основанный на веб-сайте moodle). Я знаю, что это неопределенное использование CookieContainer и HTTPCookies, потому что мы можем сначала спросить, есть ли ранее набор куки, сохраненные перед отправкой запроса на сервер. Это все равно работает без проблем, но здесь хорошая информация для чтения о WebRequest и WebResponse с примерами проектов и учебником:
Получение содержимого HTTP в .NET
Как использовать HttpWebRequest и HttpWebResponse в .NET

Ответ 5

Иногда это может помочь отключить AllowAutoRedirect и установить для обоих login POST и page GET запрос один и тот же пользовательский агент.

request.UserAgent = userAgent;
request.AllowAutoRedirect = false;