セッション状態ストア プロバイダの実装

Visual Studio 2010

更新 : 2007 年 11 月

カスタムのセッション状態ストア プロバイダの実装について説明し、サンプル プロバイダの実装方法を示します。

ASP.NET セッション状態は、ユーザー セッション データを異なるソースに格納できるように設計されています。既定では、セッション状態の値および情報は ASP.NET プロセス内のメモリに格納されます。また、セッション データを状態サーバーに格納することもできます。状態サーバーは、分離されたプロセスにセッション データを保持するため、ASP.NET アプリケーションをシャットダウンまたは再起動した場合でもセッション データが維持されます。別の方法として、SQL Server データベースにセッション データを格納し、複数の Web サーバーでデータを共有することもできます。

ASP.NET に含まれる付属のセッション状態ストアを使用するか、セッション状態ストア プロバイダを実装できます。カスタム セッション状態ストア プロバイダは次のような場合に作成します。

  • SQL Server 以外のデータ ソース (Oracle データベースなど) にセッション ステータス情報を格納する必要がある。

  • .NET Framework に付属するプロバイダが使用するデータベース スキーマとは異なるデータベース スキーマを使用してセッション ステータス情報を管理する必要がある。たとえば、既存の SQL Server データベースの定義済みスキーマに格納される買い物カゴのデータが例として挙げられる。

カスタムのセッション状態ストア プロバイダを実装するには、SessionStateStoreProviderBase クラスを継承するクラスを作成します。詳細については、このトピックで後述する「必要なクラス」を参照してください。

セッション状態は、SessionStateModule クラスで管理されます。このクラスは、セッション状態ストア プロバイダを呼び出し、要求の間に異なるタイミングでセッション データを読み取り、データ ソースに書き込みます。要求の最初に、SessionStateModule インスタンスは、GetItemExclusive メソッドを呼び出してデータ ソースからデータを取得します。または、EnableSessionState ページ属性が ReadOnly に設定されている場合は、GetItem メソッドを呼び出します。要求の最後に、セッション状態値が変更された場合、SessionStateModule インスタンスは SessionStateStoreProviderBase.SetAndReleaseItemExclusive メソッドを呼び出し、更新した値をセッション状態ストアに書き込みます。SessionStateModuleSessionStateStoreProviderBase 実装の追加のメンバを呼び出し、新規セッションを初期化します。また、HttpSessionState.Abandon メソッドが呼び出されたときは、データ ソースのセッション データを削除します。SessionStateStoreProviderBase クラスの各メンバについては、このトピックで後述する「必要なクラス」で詳しく説明します。

SessionStateModule クラスは、セッション状態ストア プロバイダに依存せずに、単独で SessionID 値を決定します。必要に応じてカスタムの SessionIDManager を実装するには、ISessionIDManager インターフェイスを継承するクラスを作成します。詳細については、「ISessionIDManager」の「解説」を参照してください。

データベース サーバーなど、セキュリティで保護されたリソースにアクセスする場合、SessionStateModule は ASP.NET のプロセス ID に戻リます。<sessionState> 構成要素の useHostingIdentity 属性を false に設定すると、IIS によって提供される ID を SessionStateModule インスタンスが偽装するように指定できます。たとえば、Windows の統合セキュリティを使用するように IIS アプリケーションを構成し、IIS によって提供される ID をセッション管理のために偽装するときは、アプリケーションの Web.config ファイルの <system.web> 構成セクションに <identity impersonate="true" /> と指定し、<sessionState> 構成要素の useHostingIdentity 属性を false に設定します。useHostingIdentity 属性が true の場合、データ ソースに接続する際に、ASP.NET はプロセス ID、つまり <identity> 構成要素に提供されるユーザー資格情報 (存在する場合) を偽装します。ASP.NET プロセス ID の詳細については、「ASP.NET プロセス ID の構成」および「ASP.NET の偽装」を参照してください。

ASP.NET アプリケーションはマルチスレッドをサポートしているため、同時実行された複数の要求に応答できます。同時実行された複数の要求が、同じセッション情報にアクセスする場合があります。フレームセット内の複数のフレームがすべて同じアプリケーションの ASP.NET Web ページを参照するシナリオを考えてみます。フレームセット内の各フレームの個々の要求は、Web サーバーの異なるスレッドで同時に実行される場合があります。各フレームの ASP.NET ページがセッション状態変数にアクセスすると、複数のスレッドが同時にセッション ストアにアクセスする可能性があります。セッション ストアでのデータの競合や予期不可能なセッション状態の動作を回避するため、SessionStateModule クラスと SessionStateStoreProviderBase クラスには、ASP.NET ページの実行時に特定のセッションのセッション ストア項目を排他的にロックする機能が含まれます。EnableSessionState 属性が ReadOnly としてマークされているときは、セッション ストア項目にロックは設定されていません。ただし、同じアプリケーションの他の ASP.NET ページがセッション ストアに書き込むことができる可能性があるため、この場合、ストアからの読み取り専用セッション データに対する要求はロックされたデータが解放されるのを待つことになります。

ロックは、GetItemExclusive メソッドの呼び出し時に、要求の先頭のセッション ストア データに設定されます。要求が完了すると、このロックは SetAndReleaseItemExclusive メソッドの呼び出し時に解放されます。

GetItemExclusive メソッドまたは GetItem メソッドの呼び出し時に、ロックされたセッション データを検出した場合、SessionStateModule インスタンスはロックが解放されるか、ExecutionTimeout プロパティの値に指定された時間を超えるまで、0.5 秒間隔でセッション データを再要求します。要求がタイムアウトした場合、SessionStateModuleReleaseItemExclusive メソッドを呼び出してセッション ストア データを解放し、その時点のセッション ストア データを要求します。

ロックされたセッション ストア データは、現在の応答に対する SetAndReleaseItemExclusive メソッドを呼び出す前に、別のスレッド上で ReleaseItemExclusive メソッドを呼び出して解放されている場合があります。その結果、SessionStateModule インスタンスは、別のセッションで既に解放されて変更されたセッション状態ストア データを設定および解放する可能性があります。このような状況を回避するため、SessionStateModule には、ロックされたセッション ストア データを変更するためのロック ID が要求ごとに含まれます。セッション ストア データは、データ ストア内のロック ID が SessionStateModule によって提供されたロック ID と一致した場合にのみ変更されます。

セッションで Abandon メソッドが呼び出された場合、そのセッションのデータは RemoveItem メソッドを使用してデータ ストアから削除されます。それ以外の場合、データはセッション データ ストアに残り、今後のセッションの要求に使用されます。

有効期限切れのデータを削除するための機構は、データ ソースの能力に依存します。有効期限切れのセッション データをセッションの Timeout プロパティに従って削除するようにデータ ソースを構成できる場合は、SetItemExpireCallback メソッドを使用して Session_OnEnd イベントのデリゲートを参照し、有効期限切れのセッション データを削除するときにこのイベントを発生させます。

セッションのスコープを維持するため、セッション状態プロバイダはアプリケーションごとに固有のセッション情報を格納します。これにより、重複するセッション ID が検出された場合でも、複数の ASP.NET アプリケーションは、競合することなく同じデータ ソースを使用できます。

セッション状態ストア プロバイダはアプリケーションごとに固有のセッション情報を格納するため、データ スキーマ、クエリ、および更新には必ずアプリケーション名を含める必要があります。たとえば、次のコマンドは、セッション データをデータベースから取得するために使用されます。

SELECT * FROM Sessions 
  WHERE SessionID = 'ABC123' AND ApplicationName = 'MyApplication'

また、セッション状態データ ストア内に、項目の一意の ID として、セッション ID とアプリケーション名の組み合わせを格納することもできます。

セッション状態ストア プロバイダを実装するには、SessionStateStoreProviderBase 抽象クラスを継承するクラスを作成します。SessionStateStoreProviderBase クラスは次に ProviderBase 抽象クラスを継承するため、ProviderBase クラスの必須メンバも実装する必要があります。ProviderBase 抽象クラスおよび SessionStateStoreProviderBase 抽象クラスから実装する必要があるプロパティおよびメソッドの一覧と、それぞれの説明を次の表に示します。各メンバの実装については、「サンプル セッション状態ストア プロバイダ」を参照してください。

ProviderBase の必須メンバ

メンバ

説明

Initialize メソッド

構成設定のプロバイダの名前と NameValueCollection インスタンスを入力として受け取ります。このメソッドを使用して、構成ファイル (Machine.config または Web.config) に指定された実装固有の値およびオプションを含むプロバイダ インスタンスに対してプロパティ値を設定します。

SessionStateStoreProvider の必須メンバ

メンバ

説明

InitializeRequest メソッド

現在の要求の HttpContext インスタンスを入力として受け取り、セッション状態ストア プロバイダが要求した初期化を実行します。

EndRequest メソッド

現在の要求の HttpContext インスタンスを入力として受け取り、セッション状態ストア プロバイダが要求したクリーンアップを実行します。

Dispose メソッド

セッション状態ストア プロバイダが使用しなくなったリソースを解放します。

GetItemExclusive メソッド

現在の要求の HttpContext インスタンスおよび現在の要求の SessionID 値を入力として受け取ります。セッションの値と情報をセッション データ ストアから取得し、要求の存続期間、データ ストアのセッション項目データをロックします。GetItemExclusive メソッドは、データ ストア内の現在のセッション状態項目の状態について呼び出し側の SessionStateModule に通知する複数の出力パラメータ値を設定します。

データ ストア内にセッション項目データが見つからない場合、GetItemExclusive メソッドは locked 出力パラメータを false に設定し、null を返します。その結果、SessionStateModuleCreateNewStoreData メソッドを呼び出して、要求に対する新しい SessionStateStoreData オブジェクトを作成します。

データ ストア内に見つかったセッション項目データがロックされている場合、GetItemExclusive メソッドは locked 出力パラメータを true に設定し、lockAge 出力パラメータを現在の日時から項目がロックされた日時を差し引いた値に設定します。また、データ ストアから取得したロック ID に lockId 出力パラメータを設定し、null を返します。その結果、SessionStateModule は、0.5 秒後に GetItemExclusive メソッドを再び呼び出してセッション項目情報を取得し、データのロックを取得します。lockAge 出力パラメータが設定した値が ExecutionTimeout 値を超えている場合、SessionStateModuleReleaseItemExclusive メソッドを呼び出してセッション項目データのロックを解除し、GetItemExclusive メソッドを再び呼び出します。

regenerateExpiredSessionId 属性が true に設定されている場合、actionFlags パラメータは Cookieless プロパティが true に設定されているセッションと共に使用されます。actionFlags 値が InitializeItem (1) に設定されている場合、セッション データ ストア内のエントリは初期化が必要な新しいセッションです。CreateUninitializedItem メソッドへの呼び出しによって、セッション データ ストア内に初期化前のエントリが作成されます。セッション データ ストアの項目が初期化済みの場合、actionFlags パラメータは 0 に設定されます。

プロバイダが Cookie なしのセッションをサポートする場合は、actionFlags 出力パラメータを現在の項目についてセッション データ ストアから返される値に設定します。要求されたセッション ストア項目の actionFlags パラメータ値が InitializeItem 列挙値 (1) に等しい場合、GetItemExclusive メソッドは、actionFlags out パラメータを設定してからデータ ストア内の値を 0 に設定します。

GetItem メソッド

このメソッドは、データ ストア内のセッション項目をロックしない点を除いて、GetItemExclusive メソッドと同じ処理を実行します。GetItem メソッドは、EnableSessionState 属性が ReadOnly に設定されているときに呼び出されます。

SetAndReleaseItemExclusive メソッド

現在の要求の HttpContext インスタンス、現在の要求の SessionID 値、格納する現在のセッション値を含む SessionStateStoreData オブジェクト、現在の要求のロック ID、および格納するデータが新しいセッションと既存のセッションのどちらのデータであるかを示す値を、入力として受け取ります。

newItem パラメータが true である場合、SetAndReleaseItemExclusive メソッドは、指定された値で新しい項目をデータ ソースに挿入します。それ以外の場合は、指定された値でデータ ソース内の既存の項目が更新され、データのロックが解放されます。指定された SessionID 値およびロック ID の値に一致する、現在のアプリケーションのセッション データだけが更新されます。

SetAndReleaseItemExclusive メソッドが呼び出された後、ResetItemTimeout メソッドが SessionStateModule によって呼び出されて、セッション項目データの有効期限 (日付と時間) が更新されます。

ReleaseItemExclusive メソッド

現在の要求の HttpContext インスタンス、現在の要求の SessionID 値、および現在の要求のロック ID を入力として受け取り、セッション データ ストア内の項目のロックを解放します。このメソッドは、GetItem メソッドまたは GetItemExclusive メソッドが呼び出され、要求された項目がロックされていることをデータ ストアが指定しているにもかかわらず、ロック期間が ExecutionTimeout 値を超えている場合に呼び出されます。このメソッドによってロックが解除され、他の要求が使用できるように項目が解放されます。

RemoveItem メソッド

現在の要求の HttpContext インスタンス、現在の要求の SessionID 値、および現在の要求のロック ID を入力として受け取り、指定された SessionID、現在のアプリケーション、および指定されたロック ID と一致するデータ ストア項目を含むデータ ストアからセッション情報を削除します。このメソッドは、Abandon メソッドが呼び出されたときに呼び出されます。

CreateUninitializedItem メソッド

現在の要求の HttpContext インスタンス、現在の要求の SessionID 値、および現在の要求のロック ID を入力として受け取り、InitializeItemactionFlags 値を持つセッション データ ストアに初期化前の項目を追加します。

CreateUninitializedItem メソッドは、regenerateExpiredSessionId 属性が true に設定されている場合に Cookie なしのセッションと共に使用されます。これにより、有効期限切れのセッション ID が検出されると、SessionStateModule は新しい SessionID 値を生成します。

新しい SessionID 値を生成するプロセスでは、新しく生成したセッション ID を含む URL にブラウザをリダイレクトする必要があります。CreateUninitializedItem メソッドは、有効期限が切れたセッション ID を含む最初の要求の間に呼び出されます。SessionStateModule は、新しい SessionID 値を取得して有効期限が切れたセッション ID を置換した後に、CreateUninitializedItem メソッドを呼び出し、初期化されていないエントリをセッション状態データ ストアに追加します。これにより、新しく生成された SessionID 値を含む URL にブラウザがリダイレクトされます。セッション データ ストア内に初期化前のエントリが存在することにより、新しく生成された SessionID 値を含むリダイレクトされた要求が有効期限切れのセッションに対する要求と間違えられることがなくなり、新しいセッションとして処理されます。

セッション データ ストア内の初期化前のエントリは新しく生成された SessionID 値に関連付けられており、有効期限 (日付と時間) などの既定値と、GetItem メソッドおよび GetItemExclusive メソッドの actionFlags パラメータに対応する値だけを含みます。セッション状態ストア内の初期化前のエントリには、InitializeItem 列挙値 (1) に等しい actionFlags 値が含まれます。この値は、GetItem メソッドと GetItemExclusive メソッドによって SessionStateModule に渡されます。また、現在のセッションが新規セッションであることを SessionStateModule に指定します。次に、SessionStateModule で新規セッションを初期化し、Session_OnStart イベントを発生させます。

CreateNewStoreData メソッド

現在の要求の HttpContext インスタンスおよび現在のセッションの Timeout 値を入力として受け取り、空の ISessionStateItemCollection オブジェクト、HttpStaticObjectsCollection コレクション、および指定された Timeout 値と共に新しい SessionStateStoreData オブジェクトを返します。ASP.NET アプリケーションの HttpStaticObjectsCollection インスタンスは、GetSessionStaticObjects メソッドを使用して取得できます。

SetItemExpireCallback メソッド

Global.asax ファイルに定義された Session_OnEnd イベントを参照するデリゲートを入力として受け取ります。セッション状態ストア プロバイダが Session_OnEnd イベントをサポートする場合は、SessionStateItemExpireCallback パラメータへのローカル参照が設定され、メソッドは true を返します。それ以外の場合、メソッドは false を返します。

Access データベースのセッション情報を管理するカスタム セッション状態ストア プロバイダの実装例については、「サンプル セッション状態ストア プロバイダ」を参照してください。

表示: