Проблемы аутентификации на сайте из кода - PullRequest
4 голосов
/ 06 марта 2012

Я пытаюсь написать код, который будет аутентифицироваться на сайте wallbase.cc.Я посмотрел на то, что он делает, используя инструменты Firfebug / Chrome Developer, и это кажется довольно простым:

Post "usrname = $ USER & pass = $ PASS & nopass_email = Type + in + your + e-mail + и + press +введите & nopass = 0 "на веб-страницу" http://wallbase.cc/user/login", сохраните возвращенные куки и используйте их для всех будущих запросов.

Вот мой код:

    private CookieContainer _cookies = new CookieContainer();

    //......

    HttpPost("http://wallbase.cc/user/login", string.Format("usrname={0}&pass={1}&nopass_email=Type+in+your+e-mail+and+press+enter&nopass=0", Username, assword));

    //......


    private string HttpPost(string url, string parameters)
    {
        try
        {
            System.Net.WebRequest req = System.Net.WebRequest.Create(url);
            //Add these, as we're doing a POST
            req.ContentType = "application/x-www-form-urlencoded";
            req.Method = "POST";

            ((HttpWebRequest)req).Referer = "http://wallbase.cc/home/";
            ((HttpWebRequest)req).CookieContainer = _cookies;

            //We need to count how many bytes we're sending. Post'ed Faked Forms should be name=value&
            byte[] bytes = System.Text.Encoding.ASCII.GetBytes(parameters);
            req.ContentLength = bytes.Length;
            System.IO.Stream os = req.GetRequestStream();
            os.Write(bytes, 0, bytes.Length); //Push it out there
            os.Close();

            //get response
            using (System.Net.WebResponse resp = req.GetResponse())
            {

                if (resp == null) return null;
                using (Stream st = resp.GetResponseStream())
                {
                    System.IO.StreamReader sr = new System.IO.StreamReader(st);
                    return sr.ReadToEnd().Trim();
                }
            }
        }
        catch (Exception)
        {
            return null;
        }
    }

После вызова HttpPost с моими параметрами входа в системуЯ ожидаю, что все будущие вызовы, использующие этот же метод, будут аутентифицированы (при условии действительного имени пользователя / пароля). Я получаю cookie сеанса в своей коллекции cookie, но по какой-то причине я не аутентифицирован. Я получаю cookie сеанса в моем cookieколлекция, независимо от того, какую страницу я посещаю, поэтому я попытался сначала загрузить домашнюю страницу, чтобы получить исходный файл cookie сеанса, а затем войти в систему, но изменений не было.

Насколько мне известно, эта версия Python работает: https://github.com/sevensins/Wallbase-Downloader/blob/master/wallbase.sh (строка 336)

Есть какие-нибудь идеи о том, как заставить работать аутентификацию?

Обновление # 1
При использовании правильной пары пользователь / парольответ автоматически перенаправляет к рефереру, но когда получена неверная пара пользователь / пароль, он не перенаправляет и возвращает неверную пару пользователь / пароль.Исходя из этого, создается впечатление, что аутентификация происходит, но, возможно, не все ключевые элементы информации сохраняются ??

Обновление # 2

Я использую .NET 3.5 .Когда я попробовал приведенный выше код в .NET 4 с добавленной строкой System.Net.ServicePointManager.Expect100Continue = false (которая была в моем коде, просто не показана здесь), она работала, никаких изменений не требовалось.Похоже, что проблема напрямую связана с какой-то проблемой, предшествующей .Net 4.

Ответы [ 3 ]

6 голосов
/ 21 июля 2012

Это основано на коде из одного из моих проектов, а также коде, найденном в различных ответах здесь на stackoverflow.

Сначала нам нужно настроить Cookie aware WebClient, который будет использовать HTML 1.0.

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

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

Затем мы устанавливаем код, который обрабатывает Authentication, и, наконец, загружаем response.

var client = new CookieAwareWebClient();
client.UseDefaultCredentials = true;
client.BaseAddress = @"http://wallbase.cc";

var loginData = new NameValueCollection();
loginData.Add("usrname", "test");
loginData.Add("pass", "123");
loginData.Add("nopass_email", "Type in your e-mail and press enter");
loginData.Add("nopass", "0");
var result = client.UploadValues(@"http://wallbase.cc/user/login", "POST", loginData);

string response = System.Text.Encoding.UTF8.GetString(result);

Мы можем попробовать это, используя HTML Visualizer, встроенный в Visual Studio, оставаясь в режиме отладки, и использовать это, чтобы подтвердить, что мы смогли authenticate и загрузить домашнюю страницу, оставаясь authenticated.

Success

Ключом здесь является настройка CookieContainer и использование HTTP 1.0 вместо 1.1. Я не совсем уверен, почему принудительное использование 1.0 позволяет успешно проходить проверку подлинности и загружать страницу, но часть решения основана на этом ответе. https://stackoverflow.com/a/10916014/408182

Я использовал Fiddler , чтобы убедиться, что ответ, отправленный C# Client, совпадает с ответом моего веб-браузера Chrome. Это также позволяет мне подтвердить правильность перенаправления C# client. В этом случае мы можем видеть, что с HTML 1.0 мы получаем HTTP/1.0 302 Found и затем перенаправляем нас на домашнюю страницу, как и предполагалось. Если мы вернемся к HTML 1.1, мы получим HTTP/1.1 417 Expectation Failed message. Fiddler

В этом потоке stackoverflow имеется некоторая информация об этом сообщении об ошибке. HTTP POST возвращает ошибку: 417 «Ожидание не выполнено».

Редактировать: Hack / Fix для .NET 3.5

Я потратил много времени, пытаясь выяснить разницу между 3,5 и 4,0, но я серьезно не понимаю. Похоже, что 3.5 создает новый файл cookie после аутентификации, и единственный способ, который я нашел для этого - дважды аутентифицировать пользователя.

Мне также пришлось внести некоторые изменения в WebClient, основываясь на информации из этого поста. http://dot -net-expertise.blogspot.fr / 2009/10 / cookiecontainer-домен-обработка-ошибка-fix.html

public class CookieAwareWebClient : WebClient
{
    public CookieContainer cookies = new CookieContainer();
    protected override WebRequest GetWebRequest(Uri address)
    {
        var request = base.GetWebRequest(address);
        var httpRequest = request as HttpWebRequest;
        if (httpRequest != null)
        {
            httpRequest.ProtocolVersion = HttpVersion.Version10;
            httpRequest.CookieContainer = cookies;

            var table = (Hashtable)cookies.GetType().InvokeMember("m_domainTable", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.GetField | System.Reflection.BindingFlags.Instance, null, cookies, new object[] { });
            var keys = new ArrayList(table.Keys);
            foreach (var key in keys)
            {
                var newKey = (key as string).Substring(1);
                table[newKey] = table[key];
            }
        }
        return request;
    }
}

var client = new CookieAwareWebClient();

var loginData = new NameValueCollection();
loginData.Add("usrname", "test");
loginData.Add("pass", "123");
loginData.Add("nopass_email", "Type in your e-mail and press enter");
loginData.Add("nopass", "0");

// Hack: Authenticate the user twice!
client.UploadValues(@"http://wallbase.cc/user/login", "POST", loginData);
var result = client.UploadValues(@"http://wallbase.cc/user/login", "POST", loginData);

string response = System.Text.Encoding.UTF8.GetString(result);
3 голосов
/ 06 марта 2012

Возможно, вам понадобится добавить следующее:

//get response
using (System.Net.WebResponse resp = req.GetResponse())
{
    foreach (Cookie c in resp.Cookies)
        _cookies.Add(c);
    // Do other stuff with response....
}

Еще одна вещь, которую вам, возможно, придется сделать, если сервер ответит 302 (перенаправление), веб-запрос .Net автоматически последует за ним, и в процессе вы можете потерять файл cookie, который вам нужен. Вы можете отключить это поведение с помощью следующего кода:

req.AllowAutoRedirect = false;
2 голосов
/ 21 июля 2012

Python, на который вы ссылаетесь, использует другого реферера (http://wallbase.cc/start/). За ним также следует другой пост (http://wallbase.cc/user/adult_confirm/1). Попробуйте другого реферера и выполните этот POST.

Я думаю, что вы правильно проходите аутентификацию, но для продолжения работы сайту требуется больше информации / подтверждений.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...