none
HTTPWebRequestでクッキーが取得できない RRS feed

  • 質問

  • お世話になっております。

    VB2005を利用して、あるサイトにアクセスしてログイン処理を行い、取得したクッキーを持ちい、その後の画面遷移での処理を行おうと考えています。

    そこで、次のようなコードを作成して実行しましたが、クッキーが取得できず、そのため、その後の画面処理に進めません。(進んでも意味がありません。)

    なお、そのサイトは、metaタグでリダイレクトの指定があります。

    ●コード
    'リクエストの作成
    Dim url = "http://xxx"
    Dim cc as CookieContainer = New CookieContainer()
    Dim req As HttpWebRequest = CType(WebRequest.Create(url), HttpWebRequest)
    req.CookieContainer = cc
    req.AllowAutoRedirect = False
    req.Referer = ...
       ...

    'POSTデータの書き込み
    Dim reqStreamWriter As StreamWriter = New StreamWriter(req.GetRequestStream())
    reqStreamWriter.Write(POSTデータ)
    reqStreamWriter.Close()
    Dim res As HttpWebResponse = req.GetResponse()

    ' レスポンスの読み取り
    Dim res As HttpWebResponse = req.GetResponse()
    Dim resStream As Stream = res.GetResponseStream()
    Dim sr As StreamReader = New StreamReader(resStream, encoder)
    Dim result As String = sr.ReadToEnd()

    Debug.Print(req.CookieContainer.Count) 【1】
    Debug.Print(res.GetResponseHeader("Set-Cookie")) 【2】

    '受信したCookieのコレクションの取得
    Dim cookies As CookieCollection = req.CookieContainer.GetCookies(req.RequestUri)
    Dim cook As Cookie
    For Each cook In cookies
    Debug.Print(cook.Name, cook.Value, cook.Expires, cook.Domain) 【3】
    Next cook

    ●コードを実行した結果

    【1】個数が取得できた
    【2】クッキーが取得できた
    【3】取得できない → ここが問題!


    ●http://xxx のHTMLソースの一部
    <meta http-equiv="refresh" content="1;URL=http://xxx/yyy" />
    リダイレクトする

    上記のような結果となり、【1】、【2】でクッキー情報が取得できたにも関わらず、【3】のクッキーコレクション情報が取得できません。(これらの結果より、正しくクッキーが取得できていないように思えます。)

    このサイトがリダイレクトを採用しているためかも知れませんが、リダイレクトを採用していないサイトでは、同様な方法でうまくいったケースがあります。

    どこか私のコードに間違いがあると思いますが、よろしくアドバイスの程お願いいたします。


    doratch
    2010年4月7日 14:41

回答

  • 外しているかもしれませんが、リダイレクト先のクッキーを取得されたいのであれば、req.RequestUriはリダイレクト前のURIのまま変化しませんので、代わりにHttpWebRequest のAddressプロパティを使用すればうまくいくかもしれません。


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://blogs.wankuma.com/trapemiya/
    • 回答としてマーク doratch 2010年4月8日 5:08
    2010年4月8日 1:55
    モデレータ
  • というか、HttpWebResponse.Cookies プロパティを使えばいいのでは…?

    あと、デバッガでブレークしてやれば CookieContainer の中にどんな Cookie がどういうドメインに格納されているか確認できます。HttpWebRequest.RequestUri や .Address、HttpWebResponse.ResponseUri などと突き合わせてみてはいかがでしょう。

    • 回答としてマーク doratch 2010年4月8日 5:09
    2010年4月8日 2:12
  • パケットキャプチャーツール (Wireshark) で先のレスに書いた試験用のページと
    のやり取りを見てみましたので、ご参考までに追加情報を書いておきます。

    最初に要求するページは cookietest.aspx で、以下のようにクッキーを書き込ん
    で CookieTestRedirect.aspx にリダイレクトするようにしてあります。

    protected void Page_Load(object sender, EventArgs e)
    {
        Response.Cookies["TestCookie"]["Font"] = "Arial";
        Response.Cookies["TestCookie"]["Color"] = "Blue";
        Response.Redirect("CookieTestRedirect.aspx");
    }

    CookieTestRedirect.aspx では Cookie の書き込みは行っていません。サーバー
    は Windows Server 2008 の IIS7 です。

    HttpWebRequest.GetResponse メソッドで cookietest.aspx をリクエストすると、
    要求/応答は以下の通り合計 4 回ありました。

    GET /Test/cookietest.aspx HTTP/1.1
    HTTP/1.1 302 Found (text/html)
    GET /Test/CookieTestRedirect.aspx HTTP/1.1
    HTTP/1.1 200 OK (text/html)

    クッキーは、上記の上から 2 つめの応答ヘッダーの中にあったのみでした。ちな
    みに、その内容は以下の通りでした。

    Set-Cookie: .ASPXANONYMOUS=dlkKJ7AOywEk...; expires=Fri, 18-Jun-2010 06:33:24 GMT; path=/; HttpOnly
    Set-Cookie: TestCookie=Font=Arial&Color=Blue; path=/

    一つ目は ASP.NET が自動的に発行する匿名ユーザー用のクッキーで、有効期限が
    設定してあるのでクライアントの HDD に保存されるようになっています。二つ目
    は試験用に作ったページ (cookietest.aspx) で書き込んだものです。

    というわけで、HttpWebRequest.CookieContainer.GetCookies(request.RequestUri)
    でならリダイレクトされてもクッキーは取得できるはずです。(実際、取得できま
    した)

    しかし、HttpWebResponse.GetResponseHeader("Set-Cookie") や HttpWebResponse.Cookies
    では取得できないということになります。(実際、取得できませんでした)


    ちなみに、IE8 で同じ試験用ページ (cookietest.aspx) にリクエストをかけてキャ
    プチャーツールで見ると、上記と同様に 4 回やり取りがされますが、ヘッダーの中
    のクッキーは異なり、以下のようになります。当然と言えば当然ですが。

    GET /Test/cookietest.aspx HTTP/1.1
        Cookie: .ASPXANONYMOUS=klSODd4OywEkAA...
    HTTP/1.1 302 Found (text/html)
        Set-Cookie: TestCookie=Font=Arial&Color=Blue; path=/
    GET /Test/CookieTestRedirect.aspx HTTP/1.1
        Cookie: .ASPXANONYMOUS=klSODd4OywEkAA...; TestCookie=Font=Arial&Color=Blue
    HTTP/1.1 200 OK (text/html)
        クッキーなし

    こんなことして、暇人だと証明しているようなものですね(笑)

    • 回答としてマーク doratch 2010年4月10日 5:36
    2010年4月10日 3:16

すべての返信

  • 外しているかもしれませんが、リダイレクト先のクッキーを取得されたいのであれば、req.RequestUriはリダイレクト前のURIのまま変化しませんので、代わりにHttpWebRequest のAddressプロパティを使用すればうまくいくかもしれません。


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://blogs.wankuma.com/trapemiya/
    • 回答としてマーク doratch 2010年4月8日 5:08
    2010年4月8日 1:55
    モデレータ
  • というか、HttpWebResponse.Cookies プロパティを使えばいいのでは…?

    あと、デバッガでブレークしてやれば CookieContainer の中にどんな Cookie がどういうドメインに格納されているか確認できます。HttpWebRequest.RequestUri や .Address、HttpWebResponse.ResponseUri などと突き合わせてみてはいかがでしょう。

    • 回答としてマーク doratch 2010年4月8日 5:09
    2010年4月8日 2:12
  • ご回答ありがとうございます。

    HttpWebRequestのAderessプロパティを使ってみましたが、結果は同様でした。


    doratch
    2010年4月8日 4:59
  • ご回答ありがとうございます。

    確かにデバッガを使えば、クッキーまわりのいろんな状態がわかりますね。

    で、いろいろ試した結果、クッキーの振る舞いは、とても奇妙で仕組みがよくわかりませんでした。

    例えば、ドメイン名の先頭にピリオドが付いたり(仕様?)、リダイレクト先に、リダイレクト前に取得したクッキーがりようできなかったり。。

    試行錯誤した結果、力業ですが、GetResponseHeader("Set-Cookie") でクッキー情報を取得し、正規表現でクッキーの適正なフォーマットに整形した後、リクエストヘッダーに書き込むことにしました。

    これにより、そのクッキーはリダイレクト先でも使えるようになりました。

    本来は、CookieContainerの仕様を見極め、適切な処理を書くのがよろしいのでしょうが、時間との兼ね合いで、今回は力業で逃げました。

    とは言え、本筋を見極めたい気持ちはありますので、そのうちきっちりと解析したいと思います。

     


    doratch
    • 回答としてマーク doratch 2010年4月8日 5:09
    • 回答としてマークされていない doratch 2010年4月8日 5:09
    2010年4月8日 5:08
  • リダイレクトされると Request 側の Cookie(【1】と【3】)は取得できても
    Response 側の Cookie(【2】)は取得できないという結果になるのではない
    でしょうか?

    何故なら、最初にリクエストをかけたページからは Cookie が発行されるよう
    になっているとしても、リダイレクトされたページでは普通は Cookie を発行
    するようになっていないと思いますので。

    試しに、ASP.NET の Web アプリで以下のようなコードを書いて試してみまし
    たが、そういう結果になりました。

    protected void Page_Load(object sender, EventArgs e)
    {
        // Cookie のテスト(書き込み)
        Response.Cookies["TestCookie"]["Font"] = "Arial";
        Response.Cookies["TestCookie"]["Color"] = "Blue";
        Response.Redirect("CookieTestRedirect.aspx");
    }

    CookieTestRedirect.aspx では Cookie の書き込みは行っていません。

    doratch さんが試した結果と異なる理由はわかりませんが、【3】で Cookie
    が取得できない理由はリダイレクトとは別のところにあるように思います。

    2010年4月8日 15:11
  • パケットキャプチャーツール (Wireshark) で先のレスに書いた試験用のページと
    のやり取りを見てみましたので、ご参考までに追加情報を書いておきます。

    最初に要求するページは cookietest.aspx で、以下のようにクッキーを書き込ん
    で CookieTestRedirect.aspx にリダイレクトするようにしてあります。

    protected void Page_Load(object sender, EventArgs e)
    {
        Response.Cookies["TestCookie"]["Font"] = "Arial";
        Response.Cookies["TestCookie"]["Color"] = "Blue";
        Response.Redirect("CookieTestRedirect.aspx");
    }

    CookieTestRedirect.aspx では Cookie の書き込みは行っていません。サーバー
    は Windows Server 2008 の IIS7 です。

    HttpWebRequest.GetResponse メソッドで cookietest.aspx をリクエストすると、
    要求/応答は以下の通り合計 4 回ありました。

    GET /Test/cookietest.aspx HTTP/1.1
    HTTP/1.1 302 Found (text/html)
    GET /Test/CookieTestRedirect.aspx HTTP/1.1
    HTTP/1.1 200 OK (text/html)

    クッキーは、上記の上から 2 つめの応答ヘッダーの中にあったのみでした。ちな
    みに、その内容は以下の通りでした。

    Set-Cookie: .ASPXANONYMOUS=dlkKJ7AOywEk...; expires=Fri, 18-Jun-2010 06:33:24 GMT; path=/; HttpOnly
    Set-Cookie: TestCookie=Font=Arial&Color=Blue; path=/

    一つ目は ASP.NET が自動的に発行する匿名ユーザー用のクッキーで、有効期限が
    設定してあるのでクライアントの HDD に保存されるようになっています。二つ目
    は試験用に作ったページ (cookietest.aspx) で書き込んだものです。

    というわけで、HttpWebRequest.CookieContainer.GetCookies(request.RequestUri)
    でならリダイレクトされてもクッキーは取得できるはずです。(実際、取得できま
    した)

    しかし、HttpWebResponse.GetResponseHeader("Set-Cookie") や HttpWebResponse.Cookies
    では取得できないということになります。(実際、取得できませんでした)


    ちなみに、IE8 で同じ試験用ページ (cookietest.aspx) にリクエストをかけてキャ
    プチャーツールで見ると、上記と同様に 4 回やり取りがされますが、ヘッダーの中
    のクッキーは異なり、以下のようになります。当然と言えば当然ですが。

    GET /Test/cookietest.aspx HTTP/1.1
        Cookie: .ASPXANONYMOUS=klSODd4OywEkAA...
    HTTP/1.1 302 Found (text/html)
        Set-Cookie: TestCookie=Font=Arial&Color=Blue; path=/
    GET /Test/CookieTestRedirect.aspx HTTP/1.1
        Cookie: .ASPXANONYMOUS=klSODd4OywEkAA...; TestCookie=Font=Arial&Color=Blue
    HTTP/1.1 200 OK (text/html)
        クッキーなし

    こんなことして、暇人だと証明しているようなものですね(笑)

    • 回答としてマーク doratch 2010年4月10日 5:36
    2010年4月10日 3:16
  • SurferOnWww様

    わざわざ検証までしてくださってありがとうございました。

    今回は、GetResponseHeader("Set-Cookie") でクッキー情報を取得し、正規表現でクッキーの適正なフォーマットに整形した後、リクエストヘッダーに書き込む、という力業で逃げましたが、本質的には、Cookieの振る舞いを見極め、良く理解した上でエレガントなコーディングをするのが良いという考えを持っています。

    そんな中で、今回検証してくださった情報については、大いに役に立ちます。

    【3】で Cookieが取得できない理由は、リダイレクト以外のところにあるようですが、いずれはきちんと究明したいと思っております。


    doratch
    2010年4月10日 5:35