HttpClient 4.x как использовать куки? - PullRequest
2 голосов
/ 10 января 2012

Я пытаюсь использовать куки, полученные в ответ на мой метод публикации, используя HttpClient 4.0.3;

Вот мой код:

public void generateRequest()
{
    DefaultHttpClient httpclient = new DefaultHttpClient();
    HttpPost httppost = new HttpPost("http://mysite.com/login");
    httpclient.getParams().setParameter("http.useragent", "Custom Browser");
    httpclient.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION,
            HttpVersion.HTTP_1_1);
    httpclient.getParams().setParameter(ClientPNames.COOKIE_POLICY,
            CookiePolicy.BROWSER_COMPATIBILITY);

    CookieStore cookieStore = new BasicCookieStore();
    HttpContext localContext = new BasicHttpContext();
    localContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);

    try
    {
        LOG.info("Status Code: sending");
        List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
        nameValuePairs.add(new BasicNameValuePair("email", "john%40gmail.com"));
        nameValuePairs.add(new BasicNameValuePair("password", "mypassword"));
        httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
        httppost.setHeader("ContentType", "application/x-www-form-urlencoded");
        HttpResponse response = httpclient.execute(httppost, localContext);
        HttpEntity entity = response.getEntity();
        if (entity != null)
        {
            entity.consumeContent();
        }
        iterateCookies(httpclient);

    }
    catch (ClientProtocolException e)
    {
        LOG.error("ClientProtocolException", e);
    }
    catch (IOException e)
    {
        LOG.error("IOException", e);
    }
}

private void iterateCookies(DefaultHttpClient httpclient)
{
    List<Cookie> cookies = httpclient.getCookieStore().getCookies();
    if (cookies.isEmpty())
    {
        System.out.println("No cookies");
    }
    else
    {
        for (Cookie c : cookies)
        {
            System.out.println("-" + c.toString());
        }
    }
}

Но я продолжаю выводить No cookies из системы, даже когда я использую web-sniffer.net, я получаю такой ответ:

Status:            HTTP/1.1 302 Found
Cache-Control:     private, no-store    
Content-Type:      text/html; charset=utf-8 
Location:          http://www.mysite.com/loginok.html   
Server:            Microsoft-IIS/7.0    
X-AspNet-Version:  2.0.50727    
Set-Cookie:        USER=DDA5FF4E1C30661EC61CFA; domain=.mysite.com; expires=Tue, 08-Jan-2013     18:39:53 GMT; path=/   
Set-Cookie:        LOGIN=D6CC13A23DCF56AF81CFAF; domain=.mysite.com; path=/ Date: Mon, 09     Jan 2012 18:39:53 GMT 
Connection:        close    
Content-Length:    165

Все примеры, которые я нашел в Интернете, которые имеют какой-либо смысл, относятся к HttpClient 3.x, где вы можете установить CookiePolicy в IGNORE и обрабатывать заголовок Set-Cookie вручную. Я не могу понять, почему это так сложно в 4.x. Мне нужен доступ к хэшу USER по ряду причин. Может кто-нибудь сказать мне, как, черт возьми, я могу получить к нему доступ?

UPDATE

Я нашел следующий C# код, который делает то же самое и работает правильно.

private static string TryGetCookie(string user, string pass, string baseurl)
    {
        string body = string.Format("email={0}&password={1}", user, pass);
        byte[] bodyData = StringUtils.StringToASCIIBytes(body);

        HttpWebRequest req = WebRequest.Create(baseurl) as HttpWebRequest;

        if (null != req.Proxy)
        {
            req.Proxy.Credentials = CredentialCache.DefaultCredentials;
        }

        req.AllowAutoRedirect = false;
        req.Method = "Post";
        req.ContentType = "application/x-www-form-urlencoded";
        req.ContentLength = bodyData.Length;

        using (Stream reqBody = req.GetRequestStream())
        {
            reqBody.Write(bodyData, 0, bodyData.Length);
            reqBody.Close();
        }

        HttpWebResponse resp1 = req.GetResponse() as HttpWebResponse;

        string cookie = resp1.Headers["Set-Cookie"];

        if( string.IsNullOrEmpty(cookie))
        {
            if (0 < resp1.ContentLength)
            {
                // it's probably not an event day, and the server is returning a singlecharacter
                StreamReader stringReader = new StreamReader(resp1.GetResponseStream());

                return stringReader.ReadToEnd();
            }

            return null;
        }

        return ParseCookie(cookie);
    }

Я считаю, что мой java-код неправильно формирует почтовый запрос, потому что когда я использую URLConnection и печатаю заголовок запроса с web-sniffer.net ниже:

POST /reg/login HTTP/1.1[CRLF]
Host: live-timing.formula1.com[CRLF]
Connection: close[CRLF]
User-Agent: Web-sniffer/1.0.37 (+http://web-sniffer.net/)[CRLF]
Accept-Charset: ISO-8859-1,UTF-8;q=0.7,*;q=0.7[CRLF]
Cache-Control: no-cache[CRLF]
Accept-Language: de,en;q=0.7,en-us;q=0.3[CRLF]
Referer: http://web-sniffer.net/[CRLF]
Content-type: application/x-www-form-urlencoded[CRLF]
Content-length: 53[CRLF]
[CRLF]
email=john%40gmail.com&password=mypassword

Я получаю ответ от сервера, который содержит заголовок set-cookies. Мой java-код не генерирует запрос так же, как web-sniffer.net?

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

PostMethod authPost = new PostMethod("http://localhost:8000/webTest/j_security_check");
// authPost.setFollowRedirects(false);
NameValuePair[] data = {
new NameValuePair("email", "john%40gmail.com"),
new NameValuePair("password", "mypassword")
};
authPost.setRequestBody(data);
status = client.executeMethod(authPost); 

Основным отличием здесь является то, что данные NameValuePair задаются в теле запроса, а не в качестве объекта. Это имеет значение? Будет ли это привести к правильному заголовку запроса?

Ответы [ 3 ]

3 голосов
/ 11 января 2012

Оба куки выглядят подозрительно. Оба используют устаревший черновой формат файлов cookie Netscape. Оба имеют недопустимое значение атрибута домена. ЛОГИН выглядит неправильно сформированным (точка с запятой отсутствует после атрибута пути). Так что, скорее всего, оба куки были отклонены HttpClient.

Вы можете узнать, так ли это, запустив HttpClient с включенным ведением журнала контекста, как описано здесь: http://hc.apache.org/httpcomponents-client-ga/logging.html

Последнее замечание. Обычно не следует вмешиваться в политику использования файлов cookie при использовании HttpClient 4.x. Политика BEST_MATCH по умолчанию автоматически делегирует обработку файлов cookie конкретной реализации спецификации файлов cookie на основе состава значения заголовка Set-Cookie. Чтобы полностью отключить обработку файлов cookie, необходимо удалить перехватчики протокола обработки файлов cookie из цепочки обработки протоколов.

Надеюсь, это поможет.

0 голосов
/ 12 января 2012

Это всегда простой ответ! После отладки C # и другой программы на C я нашел. Я прыгал и делал свою собственную кодировку на адресе электронной почты, чтобы удалить символ @. Это была проблема !!! Ничто другое, казалось, не имело значения, было ли это там или нет! Код теперь выглядит так:

public void postData(final String email, final String password)
{
    DefaultHttpClient client = new DefaultHttpClient();
    HttpPost post = new HttpPost(LOGIN_URL);
    client.getParams().setParameter("http.useragent", "Custom Browser");
    client.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);

    try
    {
        List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
        nameValuePairs.add(new BasicNameValuePair("email", email));
        nameValuePairs.add(new BasicNameValuePair("password", password));
        UrlEncodedFormEntity entity = new UrlEncodedFormEntity(nameValuePairs, HTTP.UTF_8);
        entity.setContentType("application/x-www-form-urlencoded");
        post.setEntity(entity);

        printHeaders(client.execute(post));
        printCookies(client.getCookieStore());
    }
    catch (ClientProtocolException e)
    {
        LOG.error("ClientProtocolException", e);
    }
    catch (IOException e)
    {
        LOG.error("IOException", e);
    }
}

и вывод теперь выглядит так:

Response Headers:
-Cache-Control: private, no-store
-Content-Type: text/html; charset=utf-8
-Server: Microsoft-IIS/7.0
-X-AspNet-Version: 2.0.50727
-Set-Cookie: USER=3D907C0EB817FD7...92F79616E6E96026E24; domain=.mysite.com; expires=Thu, 10-Jan-2013 20:22:16 GMT; path=/
-Set-Cookie: LOGIN=7B7028DC2DA82...5CA6FB6CD6C2B1; domain=.mysite.com; path=/
-Date: Wed, 11 Jan 2012 20:22:16 GMT
-Content-Length: 165
-Cookie::   [version: 0][name: USER][value: 3D907C0E...E26E24][domain: .mysite.com][path: /][expiry: Thu Jan 10 20:22:16 GMT 2013]
-Cookie::   [version: 0][name: LOGIN][value: 7B7028D...D6C2B1][domain: .mysite.com][path: /][expiry: null]
0 голосов
/ 10 января 2012

Я считаю, что проблема в том, что вы смешиваете два «стиля»: с одной стороны, вы создаете свой собственный BasicCookieStore и помещаете его в свой HttpContext;с другой стороны, при печати файлов cookie вы перебираете хранилище файлов cookie в DefaultHttpClient.

. Таким образом, либо измените iterateCookies, чтобы использовать локальное хранилище файлов cookie, либо просто используйте тот, который предоставлен * 1006.*.Как вы можете видеть в javadoc из DefaultHttpClient, он должен автоматически добавлять ответные файлы cookie во внутреннее хранилище файлов cookie.

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