クリックして評価とフィードバックをお寄せください
MSDN
MSDN ライブラリ
テクニカルドキュメント
Visual Studio .NET
技術資料
 ASP_NET での Cookie の基礎

  低帯域幅での表示をオンにする
このページは次のバージョンについて記述しています。
Microsoft Visual Studio 2003/.NET Framework 1.1

その他のバージョンについては、以下の情報を参照してください。
ASP.NET での Cookie の基礎

Mike Pope
Visual Basic User Education
Microsoft Corporation

January 2003
日本語版最終更新日 2003 年 2 月 28 日

概要 : ASP.NET Web アプリケーションで、Visual Basic を使用して HTTP Cookie の読み取りと書き込みを行う方法を説明します。

対象

  • ASP.NET
  • Microsoft® Visual Studio® .NET
  • Web フォーム

レベル : 初級 Web プログラマ

目次

はじめに
Cookie とは ?
Cookie の制限事項
Cookie の書き込み
多値 Cookie (サブキー)
Cookie スコープの制御
Cookie の読み取り
Cookie の変更と削除
Cookie とセキュリティ
ブラウザが Cookie を受け入れるかどうかの確認
Cookie とセッション状態

はじめに

Cookie は、Web アプリケーションにユーザー固有の情報を格納する手段を提供します。たとえば、ユーザーがサイトを訪れたとき、Cookie を使用してユーザーの好みやその他の情報を格納できます。そのユーザーが再度 Web サイトに訪れたとき、アプリケーションは以前に格納した情報を取得できます。

この資料では、ASP.NET アプリケーションで Cookie を使った作業の概要を説明します。ここでは、ASP.NET で Cookie を書き込み、後でそれを読み取るなど、Cookie を使った作業の方法論を紹介するつもりです。その後、Cookie のさまざまな機能や、(場合によっては) Cookie の変わった動作、さらに ASP.NET での Cookie のサポートを説明する予定です。

Cookie とは ?

Cookie は、要求やページが Web サーバーとブラウザ間を移動するときに、その要求やページに付随する少量のテキストです。 Cookie は、ユーザーがサイトに訪れたときに Web アプリケーションがいつでも読み取れる情報を保持します。

ユーザーが仮に www.contoso.com というサイトからページを要求したときに、そのサイトのアプリケーションがページだけでなく、日付と時刻を保持する Cookie も送信すると考えてください。そのユーザーのブラウザはそのページを取得し、同時に Cookie も取得して、ユーザーのハード ディスク上のフォルダに Cookie を格納します。

その後、そのユーザーがそのサイトから再度ページを要求します。ユーザーが URL www.contoso.com を入力すると、ブラウザはローカル ハード ドライブ上でその URL に関連付けられた Cookie を検索します。 Cookie が存在する場合は、ブラウザはページ要求と共にその Cookie をサイトに送信します。その後、アプリケーションはそのユーザーがそのサイトに最後に訪れた日付と時刻を判断できます。アプリケーションはその情報を使って、ユーザーにメッセージを表示したり、有効期限の日付を確認したり、またはその他の役立つ任意の機能を実行できます。

Cookie は、特定のページではなく Web サイトに関連付けられるので、ブラウザとサーバーはユーザーがそのサイトからどのページを要求しても www.contoso.com Cookie 情報を交換できるでしょう。ユーザーが別のサイトを訪れると、それぞれのサイトが同様にユーザーのブラウザに Cookie を送信します。ブラウザはすべての Cookie を個別に格納します。

これが、Cookie が機能する基本的な方法です。しかし、Cookie はどういうことに適しているのでしょう ? 基本的には、Cookie は Web サイトが訪問者に関する情報を格納するのに役立ちます。より一般的に言えば、Cookie は Web アプリケーションでの連続性を維持する (形式的に言えば、"状態管理" を実行する) 1 つの方法です。ブラウザと Web サーバーが実際に情報を交換している短時間を除けば、ブラウザと Web サーバーは切断されています。 Web サーバーに対して行う各要求は、別のすべての要求と独立したものとして扱われます。しかし、多くの場合、ユーザーがページを要求するときに、Web サーバーがそのユーザーを認識することが役に立ちます。たとえば、ショッピング サイトの Web サーバーがそれぞれの買い物客を把握できれば、そのサイトはショッピング カートやその他のユーザー固有の情報を管理できます。そのため、Cookie はアプリケーションが処理を続行する方法を認識するのに役立つ、適切な ID を提示する一種の名刺のような役割を果たします。

Cookie は、すべて Web サイトがユーザーを記憶するのに役立てることに関連したあらゆる種類の目的に使用されます。たとえば、世論調査を行うサイトは、Cookie を単純にブール値として使用して、ユーザーのブラウザが既に投票に参加したかどうかを示し、投票を二度行わないようにできます。ユーザーにログオンを求めるサイトは Cookie を使用して、ユーザーが既にログオンしていることをサイト自体に通知し、ユーザーが資格情報の入力を繰り返す必要をなくします。

Cookie に関する背景情報をより詳しく知りたい方は、 Verizon Web サイト、 http://www22.verizon.com/about/community/learningcenter/articles/displayarticle1/0,4065,1022z1,00.html Non-MS link の「How Internet Cookies Work」 (英語) という資料をお勧めします。この著者は、Cookie とは何であるか、ブラウザとサーバー間で Cookie をどのように交換するかについて詳しく説明しています。また、Cookie に関するプライバシーの重要性について適切な概要も含まれています。

余談ですが、なぜ "Cookie" と呼ばれるか不思議に思ったことはありませんか ? Jargon File (すなわち、The New Hacker's Dictionary), Version 4.3.3 には、この用語の語源に関するすばらしい定義ともっともらしい説明が記載されています。 http://www.catb.org/~esr/jargon/(英語) Non-MS link でこのエントリを見つけることができます。

ここからは、読者が Cookie とは何であり、ASP.NET アプリケーションでなぜ Cookie を使用するかを理解したと仮定して話を進めます。

Cookie の制限事項

Cookie を使って作業する方法論の話を始める前に、Cookie を使った作業に関するいくつかの制限事項について説明しておきましょう。大部分のブラウザは最大 4096 バイトまでの Cookie をサポートします。つまり、ユーザーのコンピュータに少量の値を格納する領域は十分ありますが、データセットや大量になりかねないその他のデータを Cookie に格納したいとは思わないでしょう。実際、おそらく Cookie にユーザー情報の大きなコレクションを格納したくはないでしょう。代わりに、ユーザー番号やその他の ID を格納します。その後、ユーザーがサイトに再度訪れたときは、そのユーザー ID を使用してデータベースでユーザーの詳細を検索します。 (ただし、ユーザー情報の格納に関するいくつかの注意事項について、「Cookie とセキュリティ」を参照してください。)

ブラウザは、サイトがユーザーのコンピュータに Cookie をいくつ格納できるかについても制限を課します。ほとんどのブラウザは、サイトごとに Cookie を 20 個だけ許可します。それ以上 Cookie を格納しようとすると、最も古い Cookie が破棄されます。また、一部のブラウザは、すべてのサイトから受け入れる Cookie の総数に絶対的な制限を設けています。この制限数は通常 300 です。

Cookie を使って作業をする場合に陥りやすい制限事項は、ブラウザが Cookie を拒否するようにユーザーが設定できることです。 Cookie をまったく使用せず、異なるメカニズムを使用してユーザー固有の情報を格納すること以外に、この問題を回避するためにできることはほとんどありません。ユーザー情報を格納するための一般的な手法はセッション状態ですが、この資料の後半の「Cookie とセッション状態」で説明するように、セッション状態は Cookie に依存します。

注意  Web アプリケーションでの状態管理と情報を保存するためのオプションの詳細については、「Web フォームの状態管理の概要」と「状態管理に関する推奨事項」を参照してください。

より一般的な教訓はおそらく、 Cookie はアプリケーションで非常に役に立つけれども、 Cookie を格納できることに依存すべきではないということです。 Cookie の使用は、あれば便利だがなくても支障のない機能ととらえるべきです。 Cookie を使用して重要な機能をサポートしてはいけません。アプリケーションが Cookie に依存する必要がある場合は、ブラウザが Cookie を受け入れるかどうかを確認するためにテストすることができます。これを行う方法については、この資料の後半の「ブラウザが Cookie を受け入れるかどうかの確認」で説明します。

Cookie の書き込み

ページの Response プロパティを使用して Cookie を書き込みます。このプロパティは、ページによってブラウザにレンダリングされる情報を追加できるオブジェクトを公開します。 Response オブジェクトは、 Cookies という名前のコレクションをサポートします。このコレクションを使って、ブラウザに書き込む Cookie を追加します。

注意  Response オブジェクトと Request オブジェクトは、それぞれ HttpResponse クラスと HttpRequest クラスを保持するページのプロパティです。これらのオブジェクトについては簡単に説明するつもりです。 ResponseRequest に関する情報をドキュメントで検索する場合は、 HttpResponseHttpRequest を参照してください。

Cookie を作成するときに、いくつかの値を指定します。まず始めに、Cookie の名前と Cookie に格納する値を指定します。複数の Cookie を作成できるので、後で Cookie を読み取るときに Cookie を識別できるように、各 Cookie には一意な名前を付ける必要があります。 (Cookie は名前で格納されるので、同じ名前で 2 つの Cookie を作成すると、一方が他方に上書きされます。)

また、Cookie の有効期限の日付と時刻も指定できます。 Cookie は通常ユーザーのディスクに書き込まれますが、永遠に彷徨い続ける可能性もあります。そのため、Cookie の有効期限が切れる日付と時刻を指定できます。ユーザーがサイトを再度訪れると、ブラウザはまずそのサイトの Cookie のコレクションを調べます。 Cookie の有効期限が切れている場合は、ブラウザはページ要求と共にその特定の Cookie を送信することはありません。代わりに、有効期限の切れた Cookie が削除されます。 (サイトはユーザーのコンピュータに複数の Cookie を書き込めます。各 Cookie は個別に有効期限の日付と時刻を持つことができます。) ブラウザがディスク上の Cookie を管理する役割を持つことに注意してください。この事実は、アプリケーションで Cookie を使って行えることに影響します。このことについても簡単に説明する予定です。

Cookie の有効期限はどのぐらいの長さにすべきなのでしょうか ? それは、Cookie を何に使用するかによって決まります。別の表現を使えば、アプリケーションが Cookie 値をどの程度の時間有効であると見なすかによって決まります。サイトへの訪問者数を数えるために Cookie を使用している場合は、有効期限を現在から 1 年間に設定するように決断できます。これは、あるユーザーが 1 年間そのサイトに訪れていないとしたら、そのユーザーを新しい訪問者と見なせるという考え方に基づいています。それとは対照的に、Cookie を使用してユーザーの好みを保存する場合は、有効期限が切れないよう (たとえば、有効期限を 50 年にするなど) に設定するのが効果的です。ユーザーは、定期的に何度も自分の好みを再設定させられるといらいらするに違いありません。また、数分や数秒で有効期限が切れる Cookie を書き込む場合もあります。この資料の後半の「ブラウザが Cookie を受け入れるかどうかの確認」で、実際の存続期間が数秒間で計測される Cookie を作成する例を紹介します。

注意  ユーザーはコンピュータ上からいつでも Cookie を消去できることを忘れないでください。たとえ、有効期限の長い Cookie を格納しても、ユーザーがすべての Cookie を削除することを決断すれば、Cookie 内に格納されたすべての設定が消去されます。

Cookie の有効期限を設定しないと、Cookie は作成されますが、ユーザーのハード ディスクに保存されません。代わりに、その Cookie はユーザーのセッション情報の一部として管理されます。ユーザーがブラウザを閉じるか、セッションがタイムアウトすると、その Cookie は破棄されます。このような保存されない Cookie は、短時間だけ格納する必要がある情報や、セキュリティ上の理由からクライアント コンピュータのディスクに書き込むべきではない場合には役に立ちます。たとえば、ユーザーが共有のコンピュータを使用しる場合に、Cookie を書き込みたくないときは、保存されない Cookie が役に立ちます。

いくつかの方法で、Cookie を Response.Cookies コレクションに追加できます。以下の例は、これを行う 2 つの方法を示しています。


Response.Cookies("userName").Value = "mike"
Response.Cookies("userName").Expires = DateTime.Now.AddDays(1)

Dim aCookie As New HttpCookie("lastVisit")
aCookie.Value = DateTime.Now.ToString
aCookie.Expires = DateTime.Now.AddDays(1)
Response.Cookies.Add(aCookie)

この例では、"userName" と "lastVisit" という 2 つの Cookie を Cookies コレクションに追加します。最初の Cookie の場合は、 Response.Cookies コレクションの値を直接設定しています。 Response.Cookies は、型 NameObjectCollectionBase の特化されたコレクションから派生するので、この方法で値を追加できます。 .

2 番目の Cookie の場合は、Cookie オブジェクトのインスタンス (型 HttpCookie) を作成し、そのプロパティを設定後、Add メソッドを使って、その Cookie を Response.Cookies コレクションに追加しています。 HttpCookie オブジェクトのインスタンスを作成するときに、コンストラクタの一部として Cookie 名を渡す必要があります。

両方の例は、ブラウザに Cookie を書き込むという同じ作業を実行します。使用する方法は、個人の好みに大きく依存します。 2 番目の方法は Cookie プロパティの設定をいくぶん容易にできることがわかると思いますが、その違いはそれほど大きなものではありません。

どちらの方法でも、有効期限値を DateTime 型にする必要があります。また、"lastVisited" 値も DateTime 型の値ですが、この場合は DateTime 型の値を文字列に変換する必要があります。 Cookie に格納する値は、最終的に文字列として格納されます。

Cookie の簡単な調査

Cookie を作成する効果を調べると役に立つことがわかります。結局のところ、Cookie はテキスト ファイルなので、Cookie を見つけることができれば、容易に Cookie を調べることができます。ブラウザによって Cookie を格納する方法が異なります。ここでは Internet Explorer が Cookie を格納する方法を説明します。別のブラウザを使用している場合は、そのブラウザのヘルプを調べ、Cookie 処理について理解してください。

Cookie を表示する簡単な方法は、 Internet Explorer を使って Cookie を検索することです。 Internet Explorer の [ツール] メニューから [インターネット オプション] を選択します。 [全般] タブの [設定] をクリックし、 [ファイルの表示] をクリックします。 Internet Explorer が Cookie を含むすべての一時ファイルを表示するウィンドウを開きます。そのウィンドウで "Cookie:" で始まる名前を持つファイルを検索するか、テキスト ファイルを探します。 Cookie をダブルクリックして、既定のテキスト ファイルで Cookie を開きます。

または、ハード ディスク上のテキスト ファイルを検索することによって Cookie を調査できます。 Internet Explorer は、<user>@<domain>.txt という形式の名前を持つファイルにサイトの Cookie を格納します。ここで、<user> はユーザーのアカウント名です。たとえば、ユーザーの名前が mikepope で、サイト www.contoso.com を訪れたとすると、そのサイトの Cookie は mikepope@www.contoso.txt というファイルに格納されるでしょう。 (名前に mikepope@www.contoso[1].txt というようにシーケンシャル番号が含まれることがあります。)

Cookie テキスト ファイルはユーザー固有なので、アカウントで切り分けられます。たとえば、Windows XP では以下のような名前を持つディレクトリ内に Cookie ファイルが見つかるでしょう。


c:\Documents and Settings\<user>\Cookies

作成中の Cookie を見つけるには、そのディレクトリ内を最終変更日時で並べ替え、最新のファイルを検索するのが便利です。

Cookie はテキスト エディタで開くことができます。ファイルが複数の Cookie を保持する場合は、各 Cookie がアスタリスク (*) で区切られます。各 Cookie の最初の行はその Cookie の名前で、2 行目はその値です。残りの行は、有効期限の日時などの Cookie 管理情報です。また、Cookie 内には簡単なチェックサムも存在します。 Cookie 名の長さや値を変更すると、ブラウザが改ざんされたことを検出し、その Cookie を破棄します。

多値 Cookie (サブキー)

上記の例では、格納する値 (ユーザー名、最終訪問日) ごとに 1 つの Cookie を使用しています。 1 つの Cookie に名前と値の組を複数格納できます。この名前と値の組を "キー" または "サブキー" と呼びます。キーになるかサブキーになるかは、何を読み取っているかによって異なります。 (サブキーは URL 内のクエリ文字列に非常によく似ているので、おそらくその構造には馴染みがあるでしょう。) たとえば、"userName" と "lastVisit" という 2 つの個別の Cookie を作成する代わりに、 "userName" と "lastVisit" というサブキーを持つ "userInfo" という 1 つの Cookie を作成できます。

個別の Cookie を作成する代わりにサブキーを使用する理由はいくつかあります。明らかに、関連する情報または似た情報を 1 つの Cookie に配置する方が整然としています。また、すべての情報が 1 つの Cookie 内に存在するので、有効期限などの Cookie の属性がすべての情報に適用されます。 (もちろん、反対に、異なる種類の情報に別の有効期限日付を割り当てる場合は、その情報を個別の Cookie に格納すべきです。)

また、サブキーを持つ Cookie は Cookie のサイズを小さく保つ場合にも役に立ちます。この資料の前半の「Cookie の制限事項」で説明したように、 Cookie は 4096 バイトに制限され、サイトごとに 20 個を超える Cookie を格納できません。サブキーを持つ 1 つの Cookie を使用することによって、サイトに割り当てられる 20 個の Cookie を使い果たすことはめったになくなります。また、1 つの Cookie には (有効期限情報など) 約 50 文字のオーバーヘッドがあります。このオーバーヘッドが格納する値の長さに加算され、加算されたすべての長さが 4K の制限値に対して評価されます。 5 つの独立した Cookie の代わりに 5 つのサブキーを格納すると、個別の Cookie のオーバーヘッドを節約できるので、この場合約 200 バイト節約できます。

サブキーを持つ Cookie を作成するためには、1 つの Cookie を書き込むための構文のバリエーションを使用します。以下の例は、それぞれ 2 つのサブキーを持つ同じ Cookie を書き込む 2 つの方法を示します。


Response.Cookies("userInfo")("userName") = "mike"
Response.Cookies("userInfo")("lastVisit") = DateTime.Now.ToString
Response.Cookies("userInfo").Expires = DateTime.Now.AddDays(1)

Dim aCookie As New HttpCookie("userInfo")
aCookie.Values("userName") = "mike"
aCookie.Values("lastVisit") = DateTime.Now.ToString
aCookie.Expires = DateTime.Now.AddDays(1)
Response.Cookies.Add(aCookie)

Cookie スコープの制御

既定では、サイトのすべての Cookie がクライアントに同時に格納され、すべての Cookie がそのサイトへの任意の要求と共にサーバーに送信されます。つまり、サイトの各ページはそのサイトのすべての Cookie を取得します。時には、 Cookie にやや特有の動作をさせたい場合があります。次の 2 つの方法で Cookie のスコープを設定できます。

  • Cookie のスコープをサーバー上のフォルダに制限します。実際的な言い方をするなら、サイト上のアプリケーションに Cookie を制限できます。
  • スコープをドメインに設定します。その結果、Cookie にアクセスできるドメイン内のサブドメインを指定できます。

フォルダまたはアプリケーションへの Cookie の制限

サーバー上のフォルダに Cookie を制限するには、次のように Cookie の Path プロパティを設定します。


Dim appCookie As New HttpCookie("AppCookie")
appCookie.Value = "written " & Now.ToString
appCookie.Expires = Now.AddDays(1)
appCookie.Path = "/Application1"
Response.Cookies.Add(appCookie)

当然、以前に説明したように、Response.Cookies に直接設定することによって Cookie を書き込むこともできます。

パスを、サイト ルートまたは仮想ルートのどちらの物理パスにもできます。この例の結果として、Application1 フォルダまたは仮想ルート内のページのみがその Cookie を利用できることになります。たとえば、サイトが www.contoso.com という名前の場合、上記の例で作成した Cookie は、パス http://www.contoso.com/Application1/ を持つページとそのフォルダ以下のすべてのページに対して利用できます。ただし、http://www.contoso.com/Application2/ や単に http://www.contoso.com/ のようなその他のアプリケーションのページに対しては利用できないでしょう。

ヒント  Internet Explorer や Mozilla ブラウザでのテストでは、場合によってはパスの大文字と小文字を区別しているようです。通常、Windows サーバーの URL は大文字と小文字を区別しませんが、これは例外のように見えます。ユーザーがブラウザに URL をどのように入力するかは制御できませんが、アプリケーションが特定のパスに結び付けられた Cookie に依存する場合は、作成する任意のハイパーリンク内の URL の大文字と小文字の構成が Path プロパティ値の大文字と小文字の構成と一致していることを確認してください。

Cookie のスコープをドメインに設定する

既定では、Cookie は特定のドメインに関連付けられています。たとえば、サイトが www.contoso.com の場合、ユーザーがそのサイトから任意のページを要求するときに、書き込んだ Cookie がサーバーに送信されます。 (直前のセクションで説明したように、特定のパス値を持つ Cookie は除きます。) たとえば、サイトが contoso.com、sales.contoso.com、および support.contoso.com というサブドメインを持つ場合、ある特定のサブドメインに Cookie を関連付けることができます。これを行うには、次のように Cookie の Domain プロパティを設定します。


Response.Cookies("domain").Value = DateTime.Now.ToString
Response.Cookies("domain").Expires = DateTime.Now.AddDays(1)
Response.Cookies("domain").Domain = "support.contoso.com"

この方法でドメインを設定すると、指定したサブドメイン内のページに対してのみ、その Cookie を利用できます。

また、複数のサブドメインで共有される Cookie を作成するために Domain プロパティを使用することもできます。たとえば、次のようにドメインを設定します。


Response.Cookies("domain").Value = DateTime.Now.ToString
Response.Cookies("domain").Expires = DateTime.Now.AddDays(1)
Response.Cookies("domain").Domain = "contoso.com"

この結果、プライマリ ドメイン以外に sales.contoso.com と support.contoso.com に対しても Cookie が利用できるようになります。

Cookie の読み取り

ブラウザがサーバーに要求を行うときに、その要求と共に Cookie をそのサーバーに送信します。 ASP.NET アプリケーションでは、Request オブジェクトを使って Cookie を読み取ることができます。 Request オブジェクトの構造は、基本的には Response オブジェクトと同じなので、 Response オブジェクトに Cookie を書き込んだのとほぼ同じ方法で Request オブジェクトから Cookie を読み取ることができます。次の例は、"username" という名前の Cookie の値を読み取り、その値を Label コントロールに表示する 2 つの方法を示しています。


If Not Request.Cookies("userName") Is Nothing Then
   Label1.Text = Server.HtmlEncode(Request.Cookies("userName").Value)
End If

If Not Request.Cookies("userName") Is Nothing Then
   Dim aCookie As HttpCookie = Request.Cookies("userName")
   Label1.Text = Server.HtmlEncode(aCookie.Value)
End If

Cookie の値の読み取りを試みる前に、その Cookie が存在することを確認する必要があります。 Cookie が存在しないと、 System.NullReferenceException 例外が発生します。ページに Cookie の内容を表示する前に、 HttpServerUtility.HtmlEncode メソッドを呼び出して、Cookie の内容をエンコードしていることに注意してください。ここでは Cookie の内容を表示しているので、エンコードを行っています (おそらく通常はこのようなことは行いません)。また、ここでは悪意のあるユーザーが Cookie に実行可能なスクリプトを紛れ込ませていないと信じています。 Cookie のセキュリティの詳細については、「Cookie とセキュリティ」を参照してください。

注意  異なるブラウザは異なる方法で Cookie を格納するので、ブラウザが異なれば互いの Cookie を読み取れる必要はありません。たとえば、あるページを一度 Internet Explorer を使ってテストした後、別のブラウザを使って再度テストすると、 2 番目のブラウザは Internet Explorer が保存した Cookie を見つけることはできません。もちろん、大部分の人々は通常 Web とのすべての対話に同じブラウザを使用するので、ほとんどの状況でこれが問題になることはありません。ただし、たとえば、ブラウザの互換性に対してアプリケーションをテストしている場合はこれが問題になります。

Cookie 内のサブキーの値を読み取ることは、それを設定するのと同様です。以下にサブキーの値を読み取る 1 つの方法を示します。


If Not Request.Cookies("userInfo") Is Nothing Then
   Label1.Text = _
        Server.HtmlEncode(Request.Cookies("userInfo")("userName"))
   Label2.text = _
        Server.HtmlEncode(Request.Cookies("userInfo")("lastVisit"))
End If

上記の例は、サブキー "lastVisit" の値を取得しています。この値はそれ以前に DateTime 値を文字列表現で設定しています。 Cookie は値を文字列として格納することを思い出してください。そのため、lastVisit 値を日付として使用する場合は、変換が必要になります。


Dim dt As DateTime
dt = CDate(Request.Cookies("userInfo")("lastVisit"))

Cookie のサブキーは、型 NameValueCollection のコレクションとして型付けされています。そのため、個別のサブキーを取得するもう 1 つの方法は、次に示すようにサブキーのコレクションを取得し、名前によりサブキー値を取り出すことです。


If Not Request.Cookies("userInfo") Is Nothing Then
   Dim UserInfoCookieCollection As _
      System.Collections.Specialized.NameValueCollection
   UserInfoCookieCollection = Request.Cookies("userInfo").Values
   Label1.Text = Server.HtmlEncode(UserInfoCookieCollection("userName"))
   Label2.Text = Server.HtmlEncode(UserInfoCookieCollection("lastVisit"))
End If

Cookie を設定するのと同様に、 Cookie を読み取るために使用する方法は使用者の好みによって決まります。

有効期限とは ?

Cookie の名前と値を読み取ることができますが、 Cookie についてその他に知ることができることはそんなに多くはありません。 Domain プロパティと Path プロパティを取得できますが、これらのプロパティの使用には制限が付けられています。たとえば、Domain プロパティを読み込むことができますが、もちろん、ページが Cookie と同じドメインに存在しない場合は、そもそも Cookie を受け取ることはないでしょう。

読み取ることができないものに、Cookie の有効期限の日付と時刻があります。ブラウザが Cookie 情報をサーバーに送信するときに、最終的にブラウザは有効期限情報を含めません。 Expires プロパティを読み取ることはできますが、その値には常に値 0 の日付値が返されます。

上記の「Cookie の書き込み」でブラウザには Cookie を管理する役割があると説明しました。この例が Expires プロパティです。 Expires プロパティの主な目的は、ブラウザが Cookie を格納するときにハウスキーピングを実行するのを支援することです。サーバーの観点からは、Cookie は存在するか、しないかのいずれかです。サーバー側にとっては、有効期限は有益な情報ではありません。そのため、ブラウザは Cookie を送信するときにこの情報を提供しません。 Cookie の有効期限日付に関心がある場合は、この資料の後半の「Cookie の変更と削除」で簡単に説明するように、これを再設定する必要があります。

有効期限を明確にするために、ブラウザに Cookie を送信する前に Response オブジェクトに設定した Cookie の Expires プロパティを読み取ることができます。ただし、Request オブジェクトからその有効期限を再び取得することはできません。

Cookie コレクションの読み取り

上記の例は、既知の名前を持つ特定の Cookie を読み取ることを想定しています。場合によっては、そのページに対して利用できるすべての Cookie を読み取る必要がある場合があります。そのページに対して利用できるすべての Cookie の名前と値を読み取るには、以下のようなコードを使用して、Request.Cookies コレクション全体をループできます。


Dim i As Integer
Dim output As String = "
Dim aCookie As HttpCookie
For i = 0 to Request.Cookies.Count - 1
    aCookie = Request.Cookies(i)
    output &= "Cookie name = " & Server.HtmlEncode(aCookie.Name) & "<br>"
    output &= "Cookie value = " & Server.HtmlEncode(aCookie.Value) & _
        & "<br><br>"
Next 
Label1.Text = output
注意  このコードを実行するときに、おそらく "ASP.NET_SessionId" という名前の Cookie を確認することになるでしょう。これは ASP.NET がセッションの一意識別子を格納するために使用する Cookie です。セッション Cookie はユーザーのハード ディスクには保存されません。セッション Cookie の詳細については、この資料の後半の「Cookie とセッション状態」を参照してください。

上記の例の制限事項は、Cookie がサブキーを持つ場合、サブキーが名前と値を組み合わせた 1 つの文字列として表示されることです。 Cookie プロパティの HasKeys を使用して、Cookie がサブキーを持つかどうか確認できます。 Cookie がサブキーを持つ場合は、そのサブキーのコレクションにドリル ダウンして、各サブキーの名前と値を取得できます。

上記で説明したように、サブキーに関する情報を Cookie プロパティの Values から取得できます。このプロパティは型 NameValueCollection のコレクションです。サブキーの値をインデックス値により直接 Values コレクションから読み取ることができます。対応するサブキー名は、Values コレクションの AllKeys メンバから取得できます。このメンバは文字列のコレクションを返します。

以下の例は、上記の例を変更したものです。この例では HasKeys プロパティを使用してサブキーをテストし、サブキーが検出された場合は、Values コレクションからサブキーを取得します。


Dim i As Integer
Dim j As Integer
Dim output As String = "
Dim aCookie As HttpCookie
Dim subkeyName As String
Dim subkeyValue As String
For i = 0 To Request.Cookies.Count - 1
   aCookie = Request.Cookies(i)
   output &= "Name = " & aCookie.Name & "<br>"
 If aCookie.HasKeys Then
 For j = 0 To aCookie.Values.Count - 1
 subkeyName = Server.HtmlEncode(aCookie.Values.AllKeys(j))
 subkeyValue = Server.HtmlEncode(aCookie.Values(j))
 output &= "Subkey name = " & subkeyName & "<br>"
 output &= "Subkey value = " & subkeyValue & "<br><br>"
 Next
 Else
     output &= "Value = " & Server.HtmlEncode(aCookie.Value) & "<br><br>"
   End If
Next
Label1.Text = output

また、次のように NameValueCollection オブジェクトとしてサブキーを取り出すことができます。


If aCookie.HasKeys Then
Dim CookieValues As _
 System.Collections.Specialized.NameValueCollection = aCookie.Values
 Dim CookieValueNames() As String = CookieValues.AllKeys
 For j = 0 To CookieValues.Count – 1
 subkeyName = Server.HtmlEncode(CookieValueNames(j))
 subkeyValue = Server.HtmlEncode(CookieValues(j))
      output &= "Subkey name = " & subkeyName  & "<br>"
      output &= "Subkey value = " & subkeyValue & "<br><br>"
   Next
Else
   output &= "Value = " & aCookie.Value & "<br><br>"
End If
注意  ページに Cookie の値を表示するという理由だけのために Server.HtmlEncode メソッドを呼び出していることを思い出してください。単に Cookie の値をテストしている場合は、その値を使用する前にその値をエンコードする必要はありません。

Cookie の変更と削除

おそらく、Cookie の値を変更したり、有効期限を延長するために、場合によっては Cookie を変更することがあります。 (ブラウザが有効期限情報をサーバーに渡さないので、Cookie の有効期限日付を読み取れないことを思い出してください。)

もちろん、実際には、直接 Cookie を変更しません。 Request.Cookies コレクションから Cookie を取得し、それを操作できますが、その Cookie 自体はユーザーのハード ディスクのどこかに存在したままです。したがって、Cookie を変更することは、新しい値を持つ新しい Cookie を作成し、その Cookie をブラウザに送信して、クライアントの古いバージョンに上書きすることになります。

以下の例は、サイトへのユーザーの訪問回数を格納する Cookie の値を変更する方法を示しています。


Dim counter As Integer
If Request.Cookies("counter") Is Nothing Then
    counter = 0
Else
    counter = CInt(Request.Cookies("counter").Value)
End If
counter += 1
Response.Cookies("counter").Value = counter.ToString
Response.Cookies("counter").Expires = DateTime.Now.AddDays(1)

または、以下の方法を使用します。


Dim ctrCookie As HttpCookie
Dim counter As Integer
If Request.Cookies("counter") Is Nothing Then
    ctrCookie = New HttpCookie("counter")
Else
    ctrCookie = Request.Cookies("counter")
End If
counter = CInt(ctrCookie.Value) + 1
ctrCookie.Value = counter.ToString
ctrCookie.Expires = DateTime.Now.AddDays(1)
Response.Cookies.Add(ctrCookie)

Cookie の削除

Cookie の削除、つまりユーザーのハード ディスクから Cookie を物理的に削除することは、 Cookie の変更のバリエーションの 1 つです。 Cookie はユーザーのコンピュータ上に存在するので、 Cookie を直接削除することはできません。ただし、ブラウザに Cookie を削除させることができます。この技法は上記で説明した Cookie を変更するものと同じ (つまり、新しい Cookie を同じ名前で作成すること) ですが、 Cookie の有効期限を現在日より以前に設定します。ブラウザは Cookie の有効期限を確認するときに、有効期限の切れた Cookie を破棄します。

つまり、Cookie を削除するのは、有効期限を現在日より以前に設定することを除けば Cookie を作成するのと同じ技法です。以下の例は、1 つの Cookie を削除するよりもやや興味深いものです。この例は、現在のドメインのすべての Cookie を削除する 1 つの方法を示します。


Dim i As Integer
Dim cookieName As String
Dim limit As Integer = Request.Cookies.Count - 1
For i = 0 To limit
   aCookie = Request.Cookies(i)
aCookie.Expires = DateTime.Now.AddDays(-1)
   Response.Cookies.Add(aCookie)
Next

サブキーの変更または削除

個別のサブキーを変更することは、それを作成するのとまったく同じです。


Response.Cookies("userInfo")("lastVisit") = DateTime.Now.ToString
Response.Cookies("userInfo").Expires = DateTime.Now.AddDays(1)

個別のサブキーを削除する方法は、やや複雑な問題になります。 Cookie の有効期限日付をリセットすると 1 つのサブキーが削除されるのではなく、 Cookie 全体が削除されることになるので、単純に有効期限日付をリセットすることはできません。これに代わるソリューションは、サブキーを保持する Cookie の Values コレクションを操作することです。まず、Request.Cookies オブジェクトから Cookie を取得することにより、Cookie を再作成します。次に、削除するサブキーの名前を Values コレクションの Remove メソッドに渡して、 Remove メソッドを呼び出すことができます。通常は、その後、変更した Cookie を Response.Cookies コレクションに追加します。その結果、その Cookie が変更した形式でブラウザに送信されます。

以下のコードは、サブキーを削除する方法を示しています。このサンプルでは、削除するサブキーの名前を変数で指定しています。


Dim subkeyName As String
subkeyName = "userName"
Dim aCookie As HttpCookie = Request.Cookies("userInfo")
aCookie.Values.Remove(subkeyName)
aCookie.Expires = DateTime.Now.AddDays(1)
Response.Cookies.Add(aCookie)

Cookie とセキュリティ

Cookie を使って作業するときは、Cookie に本来備わっているセキュリティの脆弱性を認識しておく必要があります。この資料の前半の「Cookie とは ?」で説明したように、セキュリティはプライバシーの問題を意味するものではありません。プライバシーの多くは、Cookie に格納された情報がどのように使われるかに関心があるユーザーにとっての問題です。 Cookie でのセキュリティの問題は、クライアントからデータを取得する点では同じです。まず第 1 に、アプリケーションに関する限り、Cookie は別の形式のユーザー入力です。そのため、Cookie は盗みや改ざんの対象になります。 Cookie はユーザー所有のコンピュータで利用できるので、少なくともユーザーは Cookie 内に格納されたデータを表示できます。ユーザーがその気になれば、ブラウザが Cookie をサーバーに送信する前にその Cookie を変更することもできます。

結論から言うと、ユーザー名、パスワード、クレジット カード番号などの機密情報を Cookie に格納すべきではありません。ユーザーの手元に置くべきではないもの、または Cookie を何らかの方法で盗むかもしれない誰かの手元に置くべきではないものは Cookie に格納しないでください。

同様に、Cookie から取得した情報を疑ってください。データが書き込んだものと同じであると想定しないでください。 Cookie 値を使って作業するときは、 Web ページにユーザーがデータを入力するときに行うのと同じ保護手段を講じてください。たとえば、ここではページに値を表示する前に Cookie のコンテンツに HTML エンコーディングを適用しました。これを行うことは、ユーザーからデータを入手した後に表示するすべての情報から不適切な部分を削除する標準的な技法ですが、 Cookie を使って作業する場合は異なります。

もう 1 つの考慮点は、Cookie がブラウザとサーバー間をプレーン テキストで送信されることです。誰かが Web トラフィックを傍受し、Cookie を読み取ることができます。接続が Secure Sockets Layer (SSL、つまり https://) を使用している場合のみ Cookie が送信されるように Cookie のプロパティを設定できます。 SSL は Cookie がユーザーのコンピュータに存在する間に読み取られ、操作されるのを保護することはできませんが、通信中に Cookie が傍受されることは防ぎます。この資料で SSL について説明しませんが、 Cookie に転送時の保護を追加できることは知っておいてください。 SSL の詳細については、「Secure Sockets Layer: Protect Your E-Commerce Web Site with SSL and Digital Certificates」 (英語) を参照してください。

このようなセキュリティの問題を考慮すると、どのようにすれば Cookie を安全に使用できるのでしょうか ? Cookie には、ユーザーの好みや、少なくともアプリケーションに重大な影響を与えないその他の情報など、重要ではないデータを格納できます。ユーザー ID などの重要な情報を Cookie に格納したい場合は、 Cookie を暗号化できます。 1 つの可能な方法は ASP.NET Forms Authentication ユーティリティを使用して、 Cookie として格納される認証チケットを作成することです。この資料では暗号化について説明しませんが、 Cookie に重要なデータを格納したい場合は、傍受者や盗聴者から情報を隠す可能性を調査する必要があります。

Cookie とセキュリティの脆弱性の詳細については、資料「Mitigating Cross-site Scripting With HTTP-only Cookies」 (英語) を参照してください。

ブラウザが Cookie を受け入れるかどうかの確認

この資料の前半の「Cookie の制限事項」で、ユーザーが Cookie を拒否するように設定する可能性があるという問題について説明しました。 Cookie の書き込みや読み取りが可能かどうかをどのようにして知るのでしょうか ? サーバーはページにレンダリングされた後に何が起こるかを監視しないので、 Cookie を書き込めなくてもエラーは発生しません (たとえば、Response.Cookies は例外をスローしません)。同様に、ブラウザは現在の Cookie の設定についてサーバーに何も情報を送信しません。 (HttpBrowserCapabilities.Cookies Property プロパティは Cookie が有効かどうか通知しません。現在のブラウザが本質的に Cookie をサポートするかどうかを通知するだけです。)

Cookie を受け入れるかどうかを判断する 1 つの方法は、 Cookie を書き込んでみて、再度その Cookie を読み取ってみることです。書き込んだ Cookie を読み取れない場合は、ブラウザで Cookie がオフになっていると想定できます。

ここでは、Cookie を受け入れるかどうかをテストする方法を示す簡単な例を考案しました。このサンプルは 2 ページで構成されます。最初のページで Cookie を書き込み、その後 2 番目のページにブラウザをリダイレクトします。 2 番目のページが Cookie の読み取りを試みます。次に、URL のクエリ文字列変数にテストの結果を追加して、最初のページにブラウザをリダイレクトして戻します。

最初のページのコードは以下のようになります。


Sub Page_Load()
   If Not Page.IsPostBack Then
      If Request.QueryString("AcceptsCookies") Is Nothing Then
           Response.Cookies("TestCookie").Value = "ok"
           Response.Cookies("TestCookie").Expires = _
              DateTime.Now.AddMinutes(1)
           Response.Redirect("TestForCookies.aspx?redirect=" & _
              Server.UrlEncode(Request.Url.ToString))
      Else
           labelAcceptsCookies.Text = "Accept cookies = " & _
              Request.QueryString("AcceptsCookies")
      End If
   End If
End Sub

まず、ページはこれがポストバックかどうかを確認し、ポストバックではない場合、ページはテスト結果を保持するクエリ文字列変数 (AcceptsCookies) を検索します。クエリ文字列変数が存在しない場合は、テストは完了しなかったので、コードは "TestCookie" という Cookie を書き込みます。 Cookie を書き込んだ後、サンプルは Response.Redirect を呼び出してテスト ページに転送します (TestForCookies.aspx)。テスト ページを追加する URL は、redirect というクエリ文字列変数で、現在ページの URL を保持します。この結果、テスト実行後に個のページをリダイレクトして戻すことができます。

テストページはコードだけで構成できます。コントロールを含む必要はありません。以下に使用するコードを示します。


Sub Page_Load()
    Dim redirect As String = Request.QueryString("redirect")
    Dim acceptsCookies As String
    ' Cookie を受け入れましたか ?
    If Request.Cookies("TestCookie") Is Nothing Then
        ' Cookie が存在しない場合は、受け入れられませんでした。
        acceptsCookies = 0
    Else
        acceptsCookies = 1
        ' テスト Cookie を削除します。
        Response.Cookies("TestCookie").Expires = _
           DateTime.Now.AddDays(-1)
    End If
    Response.Redirect(redirect & "?AcceptsCookies=" & acceptsCookies, _
       True)
End Sub

コードは redirect クエリ文字列変数を読み取った後に、その Cookie を読み取ろうとします。通常の処理では、Cookie が実際に存在する場合は、その Cookie をすぐに削除します。コードはテストを終了するときに、redirect クエリ文字列変数に渡された URL から新しい URL を構築します。また、新しい URL は、テスト結果を保持するクエリ文字列を含みます。最後の手順は、その新しい URL を使って元のページにブラウザをリダイレクトすることです。

この例は非常に単純ですが、プロシージャを試み、何が起こっているかを確認することによるテストの基本原理を例示しています。明らかな改善点は、ユーザーが元のページを表示するたびにテストを繰り返さないように、固定的な記憶域に Cookie のテスト結果を保持することでしょう。ただし、このことは見た目よりもやや複雑です。 Cookie は明白な理由で機能しないことがあります。もう 1 つの可能性は、セッション状態にテスト結果を格納することです。しかし、既定ではセッション状態も Cookie に依存します。そのため、ブラウザが Cookie を受け入れない場合は、セッション状態も機能しません。この最後の問題に対するソリューションは、"cookieless" セッション状態を使用することです。次のセクションでは、セッション状態が Cookie と共に機能する方法のごく簡単な概要を示します。

Cookie とセッション状態

ユーザーがサイトにナビゲートすると、サーバーはそのユーザーがサイトに訪問し続けている間、そのユーザーとの一意なセッションを確立します。 ASP.NET は、アプリケーションがユーザー固有の情報を格納できるサーバー ベースの構造 ("セッション状態") をセッションごとに管理します。詳細については、「セッション状態」を参照してください。

ASP.NET は、ユーザーをサーバー上のセッション状態情報にマップできるように、ユーザーごとにセッション状態を監視できる必要があります。既定では、ASP.NET は非固定的な Cookie を使用してセッション状態を格納します。「Cookie の読み取り」の「Cookie コレクションの読み取り」のサンプル コードを使用した場合は、おそらく Cookie の間にセッション状態 Cookie を確認したでしょう。

しかし、ユーザーがブラウザで Cookie を無効にした場合は、セッション状態はセッション ID を格納するために Cookie を使用できないので、セッション状態は機能しません。これが、上記の「ブラウザが Cookie を受け入れるかどうかの確認」で、 Cookie のテスト後に、テスト結果をセッション状態に格納するのは実用的ではないと説明した理由です。 Cookie が機能しなければ、セッション状態も機能しません。

ASP.NET は、"cookieless" セッションの形式で回避策を提供します。アプリケーションがセッション ID を Cookie ではなく、サイト内のページの URL に格納するように構成できます。 ASP.NET はセッション ID を URL に保持することによって、その ID をブラウザに格納します。その結果、ユーザーが別のページを要求するときに、ID を再取得できます。

Cookieless セッションは Cookie を拒否するブラウザの問題を回避でき、セッション状態を使って作業できるようにします。アプリケーションがセッション状態に依存する場合は、 cookieless セッションを使用するように構成したいと考えるかもしれません。ただし、ユーザーが URL を他人と共有するようなある限られた状況、たとえば、ユーザーのセッションがまだアクティブな間にその URL を同僚に電子メールで送信するような状況では、最終的に両方のユーザーが同じセッションを共有することになり、予測できない結果になります。

cookieless session を使用するようにアプリケーションを構成することに関する詳細については、サポート技術情報の資料「[INFO] ASP.NET の状態管理について 」を参照してください。

コミュニティ コンテンツ   コミュニティ コンテンツとは
新しいコンテンツの追加 RSS  注釈
Processing
© 2009 Microsoft Corporation. All rights reserved. 使用条件  |  商標  |  プライバシー
Page view tracker