Увійдіть на веб-сайт через C #


81

Я відносно новачок у використанні C # і маю програму, яка читає частини вихідного коду на веб-сайті. Це все працює; але проблема полягає в тому, що на цій сторінці потрібен користувач, який має ввійти в систему для доступу до цього вихідного коду. Те, що моїй програмі потрібен спосіб первинного входу користувача на веб-сайт, - після цього я зможу отримати доступ і прочитати вихідний код.

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

Я цілий день шукав, як це зробити, і пробував приклади, але мені не пощастило.

Спасибі заздалегідь


Отже, я можу придумати купу способів зробити це ... Чи вимагає програма C # "код" безпосередньо з сервера за допомогою HTTP, чи ви повертаєтеся в програму браузера чи що? Потрібна трохи більше інформації.
Мітч Бейкер

Програма використовує WebClient.DownloadString ("URL")

Відповіді:


113

Ви можете продовжувати використовувати WebClient для POST (замість GET, що є дієсловом HTTP ви зараз користуєтесь із DownloadString), але я думаю, вам буде простіше працювати з (трохи) класами нижчого рівня WebRequest та WebResponse.

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


Опублікування у формі для входу

Публікації форм легко імітувати, це просто випадок форматування даних ваших публікацій таким чином:

field1=value1&field2=value2

Використовуючи 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"];

Ось приклад того, що ви повинні бачити в заголовку 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
Як я можу визначити, чи успішно аутентифіковано користувача?
Сірал

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

Дякую, після декількох годин пошуку рішення це працює!
Ессей

9

Метью Бріндлі , ваш код дуже добре працював на якомусь веб-сайті, який мені потрібен (з логіном), але мені потрібно було змінити на HttpWebRequestтаHttpWebResponse в іншому випадку я отримую 404 Bad Request з віддаленого сервера. Крім того, я хотів би поділитися своїм обхідний шлях , використовуючи свій код, і це те , що я спробував його входу на сайт на основі Мудла , але він не працює на вашому кроці « Отримання сторінки за реєстраційну форму » , тому що , коли успішно POSTING логін, заголовок'Set-Cookie' нічого не повернув, незважаючи на те, що інші веб-сайти роблять це

Тому я думаю, що саме тут нам потрібно зберігати файли cookie для наступних запитів, тому я додав це.


До блоку коду " Опублікування у форму для входу ":

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і HTTPCookie, тому що ми можемо спочатку запитати, чи раніше було збережено набір файлів cookie відправка запиту на сервер. Це в будь-якому випадку працює без проблем, але ось хороша інформація, яку можна прочитати, WebRequestа також WebResponseіз зразками проектів та підручник:
Отримання вмісту HTTP у .NET
Як користуватися HttpWebRequest та HttpWebResponse у .NET


2

Іноді це може допомогти вимкнути AllowAutoRedirectта встановити як вхід, так POSTі GETзапити на сторінку того самого агента користувача.

request.UserAgent = userAgent;
request.AllowAutoRedirect = false;
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.