2012-01-09 5 views
2

HttpClient 4.0.3を使用して私の投稿メソッドへの応答で取得するクッキーを使用しようとしています。ここでHttpClient 4.x Cookieの使い方は?

は私のコードです:

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を参照して、CookiePolicyIGNOREに設定し、Set-Cookieヘッダーを手動で処理できるオンラインを見つけました。なぜこれが難しいのか分かりません4.x。いくつかの理由から、USERハッシュにアクセスする必要があります。誰でも私にそれにアクセスできる方法を教えてもらえますか?

UPDATE

私は同じことをして、正常に動作する次C#のコードを発見しました。私はからの応答を取得

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 

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

は私が下にweb-sniffer.netからのURLConnectionを使用してリクエストヘッダを印刷するとき、私のJavaコードが正しくPOSTリクエストを形成するためにされていないと信じて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データがリクエストボディに設定ではなくエンティティとして設定されていることである:

私はこのコードを使用して生成POSTメソッドを見てきました。これは違いがありますか?これにより、正しいリクエストヘッダーが生成されますか?

答えて

0

いつも簡単な答えです! 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

ここでは、2つの「スタイル」を混在させていると思います。一方で、自分でBasicCookieStoreを作成してHttpContextに入れます。一方、クッキーを印刷するときは、DefaultHttpClientのクッキーストアをループします。

したがって、ローカルCookieストアを使用するようにiterateCookiesを変更するか、またはDefaultHttpClientによって提供されるものを使用してください。 javadocDefaultHttpClient)のように、内部Cookieストアに自動的に応答Cookieが追加されます。

+0

感謝を。しかし、反復クッキーで 'BasicCookieStore'を使用すると、DefaultHttpClientの内部クッキーストアを使用する場合と同様に、クッキーは返されません。なぜ私は考えていない... –

+0

奇妙な。数日前のプロジェクトでHttpClientを使用しました(バージョン4.1.2)。私のコードは、外部のBasicCookieStoreと非常によく似ていますが、繰り返していくとクッキーはそこにあります。 – waxwing

+0

Hmmm ...おそらく4.0.3のバグですか?私は想像することはできませんが、それはかなり大きな落とし穴です。私が設定する必要がある他のシステム変数はありますか?私は彼らがいくつかの文書で数回言及しているのを見ました。 –

3

両方のCookieが疑わしいと思われます。どちらも旧式のNetscape Cookieドラフト形式を使用しています。どちらも無効なドメイン属性値を持っています。 LOGINは、その上に不正な形式(パス属性の後にセミコロンがありません)と表示されます。したがって、おそらく両方のCookieがHttpClientによって拒否された可能性があります。 http://hc.apache.org/httpcomponents-client-ga/logging.html

最後の一つの発言:あなたはこのかどうかを確認することができます

は、ここで説明したように、コンテキストのロギングがオンになってのHttpClientを実行した場合です。一般的に、HttpClient 4.xを使用している場合は、Cookieポリシーに干渉しないでください。デフォルトのBEST_MATCHポリシーは、Set-Cookieヘッダー値の構成に基づいて、Cookieの処理を特定のCookie仕様実装に自動的に委任します。 Cookie処理を完全に無効にするには、プロトコル処理チェーンからCookie処理プロトコルインターセプタを削除する必要があります。

これが役に立ちます。

+0

洞察に感謝します。私は私の開発マシンにアクセスするとすぐにクッキーポリシーのものを削除します。上記の元の投稿への私の編集を参照すると、 'Content-type:application/x-www-form-urlencoded Content-length:53'プロパティを設定しなければ、クッキーを取得しないようです。しかし、HttpClientを使って 'Content-Length'を設定しようとすると、ContentLengthプロパティがすでに設定されているというレスポンスヘッダの例外が発生します。これがエラーを引き起こす可能性がある場合、どのような考えですか? –

+1

@Chris Robinson:コンテンツ長の値に耳を傾けないでください!これを誤算するのはかなり簡単です。 HttpClientがその仕事をし、リクエストメッセージに含まれるコンテンツエンティティの長さに基づいて値を自動的に計算させます。 – oleg

+1

@Chris Robinson:よく動作するHttpClientであるHttpClientは、Content-Typeヘッダー値にcharset属性も追加します。どうやら、WebアプリケーションはContent-Typeヘッダー値を正しく解析するにはあまりにも愚かです。 StringEntity#setCotnentType()メソッドを使用してデフォルト値をオーバーライドし、 'application/x-www-form-urlencoded'(sans charset属性)に設定します – oleg

関連する問題