SQL Server でメンバーシップ スキーマを作成する (VB)

作成者: Scott Mitchell

Note

この記事が作成された後で、ASP.NET メンバーシップ プロバイダーは ASP.NET Identity に置き換えられました。 この記事の作成時点で紹介されているメンバーシップ プロバイダーではなく、ASP.NET Identity プラットフォームを使うようにアプリを更新することを強くお勧めします。 ASP.NET メンバーシップ システムと比べると、ASP.NET Identity には次のような多くの利点があります。

  • パフォーマンスの向上
  • 向上した拡張性とテストの容易性
  • OAuth、OpenID Connect、2 要素認証のサポート
  • クレームベースの ID のサポート
  • ASP.Net Core との相互運用性の向上

コードのダウンロードまたは PDF のダウンロード

このチュートリアルでは、まず、SqlMembershipProvider を使用するために必要なスキーマをデータベースに追加する方法を調べることから始めます。 その後、スキーマのキー テーブルを調べ、その目的と重要性について説明していきます。 このチュートリアルは、メンバーシップ フレームワークが使用する必要があるプロバイダーを、ASP.NET アプリケーションに指示する方法について説明して終了します。

はじめに

前の 2 つのチュートリアルでは、フォーム認証を使用した Web サイトの訪問者の識別について見てきました。 フォーム認証フレームワークを使用すると、開発者はユーザーを Web サイトにログインさせ、認証チケットを使用して、そのユーザーをページ アクセス間で簡単に記憶することができます。 この FormsAuthentication クラスには、チケットを生成して、それを訪問者の Cookie に追加するためのメソッドが含まれています。 FormsAuthenticationModule では、受信する要求がすべて調べられ、有効な認証チケットを持つ要求に対しては GenericPrincipalFormsIdentity オブジェクトが作成され、それらが現在の要求に関連付けられます。 フォーム認証は、ログイン時に訪問者に認証チケットを付与し、それ以降の要求では、そのチケットを解析してユーザーの ID を判断するためだけのメカニズムです。 依然として、Web アプリケーションでユーザー アカウントをサポートするには、ユーザー ストアを実装し、資格情報の検証、新しいユーザーの登録、その他非常に多くのユーザー アカウント関連タスクを追加する必要があります。

ASP.NET 2.0 以前、開発者は、これらのユーザー アカウント関連のすべてのタスクを実装する仕事を背負っていました。 幸いなことに、ASP.NET チームはこの欠点を認識しており、ASP.NET 2.0 では、メンバーシップ フレームワークを導入しました。 メンバーシップ フレームワークは、NET Framework に含まれるクラスのセットであり、ユーザー アカウント関連の主要タスクを実行するためのプログラマティック インターフェイスを提供します。 このフレームワークはプロバイダー モデルの上に構築されており、開発者はカスタマイズされた実装を標準化された API にプラグインできます。

セキュリティの基本と ASP.NET サポート」のチュートリアルで説明したように、.NET Framework には、2 つの組み込みのメンバーシップ プロバイダー、ActiveDirectoryMembershipProvider および SqlMembershipProvider が付属しています。 その名前が示すように、SqlMembershipProvider では、ユーザー ストアとして Microsoft SQL Server データベースが使用されます。 アプリケーションでこのプロバイダーを使用するには、ストアとして使用するデータベースを、そのプロバイダーに伝える必要があります。 ご想像のとおり、SqlMembershipProvider では、ユーザー ストア データベースに特定のデータベース テーブル、ビュー、ストアド プロシージャが備わっていることを想定しています。 この想定されたスキーマは、選択したデータベースに追加する必要があります。

このチュートリアルでは、まず、SqlMembershipProvider を使用するために、必要なスキーマをデータベースに追加する手法を調べることから始めます。 その後、スキーマのキー テーブルを調べ、その目的と重要性について説明していきます。 このチュートリアルは、メンバーシップ フレームワークが使用する必要があるプロバイダーを、ASP.NET アプリケーションに指示する方法について説明して終了します。

それでは始めましょう。

手順 1: ユーザー ストアを配置する場所を決定する

ASP.NET アプリケーションのデータは、通常、データベース内の多数のテーブルに保存されます。 SqlMembershipProvider データベース スキーマを実装する際には、メンバーシップ スキーマの配置場所を、アプリケーション データと同じデータベースにするか、代替データベースにするかを決定する必要があります。

メンバーシップ スキーマを置く場所は、次の理由から、アプリケーション データと同じデータベースにすることをお勧めします。

  • 保守のしやすさ データが 1 つのデータベースにカプセル化されているアプリケーションは、2 つの別個のデータベースを持つアプリケーションよりも容易に理解、保守、デプロイできます。
  • 関係の整合性 アプリケーション テーブルと同じデータベースにメンバーシップ関連のテーブルを配置することで、メンバーシップ関連テーブルと関連アプリケーション テーブルの主キーの間で、外部キーの制約を確立することができます。

ユーザー ストアとアプリケーション データを個別のデータベースに分離するのは、それぞれが個別のデータベースを使用する複数のアプリケーションを使用していて、それらが共通のユーザー ストアを共有する必要がある場合にのみ合理性があります。

データベースの作成

2 番目のチュートリアル以降に構築してきたアプリケーションは、これまでデータベースを必要としていませんでした。 しかしここでは、ユーザー ストアにそれが必要となります。 では、それを作成して、SqlMembershipProvider プロバイダーに必要なスキーマを追加してみましょう (手順 2 を参照)。

Note

このチュートリアル シリーズでは、Microsoft SQL Server 2005 Express Edition データベースを使用して、アプリケーション テーブルと SqlMembershipProvider スキーマを保存していきます。 この決定には、次の 2 つの理由があります。第一に、コストが無料だということです。Express Edition は SQL Server 2005 でも最も読み取りとアクセスが簡単なバージョンです。第二に、SQL Server 2005 Express Edition データベースを、Web アプリケーションの App_Data フォルダーに直接配置できることです。データベースと Web アプリケーションが 1 つの ZIP ファイルにパッケージ化できるので、特別なセットアップ手順や構成オプションなしで再デプロイできます。 Express Edition 以外のバージョンの SQL Server を使いたい場合も、難しく考える必要はありません。 手順は実質的に同じです。 SqlMembershipProvider スキーマは、Microsoft SQL Server 2000 以上の任意のバージョンで動作します。

ソリューション エクスプローラーで、App_Data フォルダーを右クリックし、[新しい項目の追加] を選択します (プロジェクトに App_Data フォルダーが表示されない場合は、ソリューション エクスプローラーでプロジェクトを右クリックし、[ASP.NET フォルダーの追加]、App_Data の順に選択します)。[新しい項目の追加] ダイアログ ボックスで、SecurityTutorials.mdf という名前の新しい SQL Database を選択します。 このチュートリアルでは、このデータベースに SqlMembershipProvider スキーマを追加します。アプリケーション データをキャプチャするための追加のテーブルは、この後のチュートリアルで作成します。

Add a New SQL Database Named SecurityTutorials.mdf Database to the App_Data Folder

図 1: App_Data フォルダーに SecurityTutorials.mdf Database という名前で新しい SQL Database を追加する (クリックするとフルサイズの画像が表示されます)

App_Data フォルダーに追加したデータベースは、自動的に、データベース エクスプローラー ビューにも表示されます (Express Edition バージョン以外の Visual Studio の場合、データベース エクスプローラーはサーバー エクスプローラーと呼ばれます)。データベース エクスプローラーに移動し、ここで追加した SecurityTutorials データベースを展開します。 画面にデータベース エクスプローラーが表示されない場合は、[表示] メニューで [データベース エクスプローラー] を選択するか、Ctrl + Alt + S キーを押します。 図 2 に示すように、この SecurityTutorials データベースは空の状態で、テーブルもビューもストアド プロシージャも含まれていません。

The SecurityTutorials Database is Currently Empty

図 2: 現在、空の状態の SecurityTutorials データベース (クリックするとフルサイズの画像が表示されます)

手順 2: データベースに SqlMembershipProvider スキーマを追加する

SqlMembershipProvider では、特定のテーブル、ビュー、ストアド プロシージャのセットを、ユーザー ストアのデータベースにインストールする必要があります。 これらの必要なデータベース オブジェクトは、aspnet_regsql.exe ツールを使用して追加できます。 このファイルは %WINDIR%\Microsoft.Net\Framework\v2.0.50727\ フォルダー内にあります。

Note

aspnet_regsql.exe ツールでは、コマンド ライン機能とグラフィカル ユーザー インターフェイスの両方が利用できます。 グラフィカル インターフェイスは、ユーザーにとって使いやすく、このチュートリアルではそれを確認していきます。 コマンド ライン インターフェイスは、ビルド スクリプトや自動テスト シナリオなどで、SqlMembershipProvider スキーマの追加を自動化したい場合に便利です。

この aspnet_regsql.exe ツールは、指定した SQL Server データベースに対して、ASP.NET アプリケーション サービスを追加または削除するために使用されます。 ASP.NET アプリケーション サービスには、他の ASP.NET 2.0 フレームワーク向けの SQL ベース プロバイダーのスキーマと合わせて、SqlMembershipProvider および SqlRoleProvider 向けのスキーマが含まれています。 aspnet_regsql.exe ツールには、次の 2 ビットの情報を提供する必要があります。

  • アプリケーション サービスを追加または削除するかどうか、および
  • アプリケーション サービス スキーマの追加または削除元のデータベース

aspnet_regsql.exe ツールは、使用するデータベースのプロンプトで、データベースが存在するサーバーの名前、データベースに接続するためのセキュリティ資格情報、そのデータベース名を提供するよう要求します。 SQL Server のExpress 以外のエディションを使用している場合も、ユーザーはこの情報を既に把握しています。これは、ASP.NET の Web ページからデータベースを操作するときに、接続文字列を経由して指定する必要があるものと同じ情報です。 ただし、App_Data フォルダー内で SQL Server 2005 Express Edition データベースを使用する場合の、サーバー名とデータベース名の決定は、もう少し複雑になります。

次のセクションでは、App_Data フォルダー内の SQL Server 2005 Express Edition データベースのサーバー名とデータベース名を、簡単に指定する方法について説明します。 SQL Server 2005 Express Edition を使用していない場合は、ここをスキップして、「アプリケーション サービスのインストール」セクションに進むことができます。

App_Data フォルダー内の SQL Server 2005 Express Edition データベースのサーバー名とデータベース名を決定する

この aspnet_regsql.exe ツールを使用するには、サーバー名とデータベース名を知る必要があります。 サーバー名は localhost\InstanceName です。 ほとんどの場合、InstanceNameSQLExpress です。 ただし、SQL Server 2005 Express Edition を手動でインストールした場合 (つまり、Visual Studio のインストール中に自動的にインストールしなかった場合) には、異なるインスタンス名を選択している可能性があります。

データベース名の決定方法は少し複雑です。 通常、App_Data フォルダー内のデータベースは、グローバルの一意識別子とデータベース ファイルへのパスを含む、データベース名を持っています。 aspnet_regsql.exe を介してアプリケーション サービス スキーマを追加するには、このデータベースの名前を確定する必要があります。

データベース名を確認する最も簡単な方法は、SQL Server Management Studio を使用して調べることです。 SQL Server 2005 データベースを管理するためのグラフィカル インターフェイスは、SQL Server Management Studio では提供されますが、SQL Server 2005 の Express Edition には付属していません。 幸い、SQL Server Management Studio の無料の Express Edition をダウンロードすることができます

Note

デスクトップに Express Edition 以外のバージョンの SQL Server 2005 もインストールされている場合なら、完全なバージョンの Management Studio がインストールされていると思います。 この完全なバージョンを使用して、以下で説明する手順に従い、Express Edition 向けにデータベース名を決定できます。

まず、Visual Studio を閉じて、データベース ファイルに対して Visual Studio が課したすべてのロックが閉じられるようにします。 次に、SQL Server Management Studio を起動し、SQL Server 2005 Express Edition の localhost\InstanceName データベースに接続します。 前述のように、インスタンス名は SQLExpress だと思われます。 [認証] オプションで、[Windows 認証] を選択します。

Connect to the SQL Server 2005 Express Edition Instance

図 3: SQL Server 2005 Express Edition インスタンスに接続する (クリックするとフルサイズの画像が表示されます)

SQL Server 2005 Express Edition インスタンスに接続すると、Management Studio にはデータベース、セキュリティ設定、サーバー オブジェクトなどのフォルダーが表示されます。 [データベース] タブを展開すると、SecurityTutorials.mdf データベースがデータベース インスタンスに登録されていないことがわかります。つまり、データベースを最初にアタッチする必要があります。

データベース フォルダーを右クリックし、コンテキスト メニューから [アタッチ] を選択します。 これで、[データベースのアタッチ] ダイアログ ボックスが表示されます。 ここから [追加] ボタンをクリックし、SecurityTutorials.mdf データベースを参照して、[OK] をクリックします。 図 4 は、SecurityTutorials.mdf データベースが選択された後の、[データベースのアタッチ] ダイアログ ボックスを示しています。 図 5 は、データベースが正常にアタッチされた後の、Management Studio のオブジェクト エクスプローラーを示しています。

Attach the SecurityTutorials.mdf Database

図 4: SecurityTutorials.mdf データベースのアタッチ (クリックするとフルサイズの画像が表示されます)

The SecurityTutorials.mdf Database Appears in the Databases Folder

図 5: データベース フォルダーに表示された SecurityTutorials.mdf データベース (クリックするとフルサイズの画像が表示されます)

図 5 に示すように、SecurityTutorials.mdf データベースの名前はかなり難解です。 これを、より記憶しやすい (入力しやすい) 名前に変更しましょう。 データベースを右クリックし、コンテキスト メニューから [名前の変更] を選択し、名前を「SecurityTutorialsDatabase」に変更します。 これでも、ファイル名が変更されることはなく、SQL Server に対してデータベースが自身を特定するための名前が変更されるだけです。

Rename the Database to SecurityTutorialsDatabase

図 6: データベースの名前を SecurityTutorialsDatabase に変更する (クリックするとフルサイズの画像が表示されます)

この時点で、SecurityTutorials.mdf データベース ファイル向けのサーバー名とデータベース名がそれぞれ localhost\InstanceNameSecurityTutorialsDatabase であることがわかっています。 これで、aspnet_regsql.exe ツールを使用してアプリケーション サービスをインストールする準備ができました。

アプリケーション サービスのインストール

aspnet_regsql.exe ツールを起動するには、スタート メニューに移動し、[実行] を選択します。 テキストボックスに「%WINDIR%\Microsoft.Net\Framework\v2.0.50727\aspnet_regsql.exe」と入力し、[OK] をクリックします。 または、Windows のエクスプローラーを使用して、適切なフォルダーの内部に移動し、aspnet_regsql.exe ファイルをダブルクリックすることもできます。 どちらの方法でも同じ結果が得られます。

コマンド ライン引数を一切指定せずに aspnet_regsql.exe ツールを実行すると、ASP.NET SQL Server セットアップ ウィザードの、グラフィカル ユーザー インターフェイスが起動します。 ウィザードを使用すると、指定したデータベース上で、ASP.NET アプリケーション サービスを簡単に追加または削除できます。 図 7 に示したウィザードの最初の画面では、このツールの目的が説明されます。

Use the ASP.NET SQL Server Setup Wizard Makes to Add the Membership Schema

図 7: ASP.NET SQL Server セットアップ ウィザードを使用してメンバーシップ スキーマを追加する (クリックするとフルサイズの画像が表示されます)

ウィザードの 2 番目の手順では、アプリケーション サービスを追加するか削除するかを尋ねられます。 ここでは、SqlMembershipProvider に必要なテーブル、ビュー、ストアド プロシージャを追加しようとしているので、[アプリケーション サービス] のオプションで [SQL Server の構成] を選択します。 後でデータベースからこのスキーマを削除する場合、このウィザードを再実行しますが、その際は、[既存のデータベースからアプリケーション サービス情報を削除する] オプションを選択します。

Choose the Configure SQL Server for Application Services Option

図 8: アプリケーション サービスの [SQL Server の構成] オプションを選択する (クリックするとフルサイズの画像が表示されます)

3 番目の手順では、データベース情報 (サーバー名、認証情報、データベース名) の入力を求められます。 これまでこのチュートリアルに従って操作しており、App_DataSecurityTutorials.mdf データベースを追加し、それを localhost\InstanceName にアタッチし、さらに名前を SecurityTutorialsDatabase に変更してある場合、次の値を使用します。

  • サーバー: localhost\InstanceName
  • Windows 認証
  • データベース: SecurityTutorialsDatabase

Enter the Database Information

図 9: データベース情報を入力する (クリックするとフルサイズの画像が表示されます)

データベース情報を入力したら、[次へ] をクリックします。 最後の手順では、実行される手順の概要が示されます。 [次へ] をクリックしてアプリケーション サービスをインストールし、[完了] をクリックしてこのウィザードを完了します。

Note

データベースのアタッチとデータベース ファイルの名前変更に Management Studio を使用した場合は、Visual Studio を再度開く前に、必ずデータベースをデタッチして Management Studio を閉じておきます。 SecurityTutorialsDatabase データベースをデタッチするには、データベース名を右クリックし、[タスク] メニューから [デタッチ] を選択します。

ウィザードが完了したら、Visual Studio に戻り、データベース エクスプローラーに移動します。 [テーブル] フォルダーを展開します。 名前がプレフィックス aspnet_ で始まる一連のテーブルが表示されます。 同様に、さまざまなビューとストアド プロシージャが、ビュー フォルダーとストアド プロシージャ フォルダーの下にあります。 これらのデータベース オブジェクトが、アプリケーション サービス スキーマを構成しています。 メンバーシップおよびロールに固有のデータベース オブジェクトについては、手順 3 で見ていきます。

A Variety of Tables, Views, and Stored Procedures Have Been Added to the Database

図 10: データベースに追加された各種のテーブル、ビュー、ストアド プロシージャ (クリックするとフルサイズの画像が表示されます)

Note

aspnet_regsql.exe ツールのグラフィカル ユーザー インターフェイスは、アプリケーション サービス スキーマ全体をインストールします。 また、コマンド ラインから aspnet_regsql.exe を実行した場合には、インストール (または削除) したい特定のアプリケーション サービス コンポーネントを指定できます。 したがって、SqlMembershipProvider および SqlRoleProvider プロバイダーに必要なテーブル、ビュー、ストアド プロシージャのみを追加する場合は、コマンド ラインから aspnet_regsql.exe を実行します。 あるいは、aspnet_regsql.exe で使用される T-SQL 作成スクリプトの適切なサブセットを、手動で実行することもできます。 これらのスクリプトは WINDIR%\Microsoft.Net\Framework\v2.0.50727\ フォルダーにあり、InstallCommon.sqlInstallMembership.sqlInstallRoles.sqlInstallProfile.sqlInstallSqlState.sql などの名前が付けられています。

この時点で、SqlMembershipProvider が必要とするデータベース オブジェクトが作成されています。 とはいえ、まだ、メンバーシップ フレームワークに対しては SqlMembershipProvider を (ActiveDirectoryMembershipProvider などではなく) 使用し、SqlMembershipProvider に対しては SecurityTutorials データベースを使用するように、指示する必要があります。 手順 4 で、使用するプロバイダーを指定する方法と、選択したプロバイダーの設定をカスタマイズする方法について説明します。 しかし、まずは、先ほど作成したデータベース オブジェクトについて詳しく見ることにしましょう。

手順 3: スキーマのコア テーブルの概観

ASP.NET アプリケーションでメンバーシップ フレームワークとロール フレームワークを操作する場合、その実装の詳細はプロバイダーによってカプセル化されています。 この後のチュートリアルでは、.NET Framework の Membership および Roles クラスを介して、これらのフレームワークとのインターフェイスを作成していきます。 これらの高度な API を使用すれば、どのクエリが実行されるかや、SqlMembershipProvider および SqlRoleProvider によってどのテーブルが変更されるかなどの、低レベルの詳細事項に気を払う必要はありません。

このため、手順 2 で作成したデータベース スキーマを調べることなく、メンバーシップとロールのフレームワークを安心して使用できます。 ただし、アプリケーション データを保存するためにテーブルを作成する場合は、ユーザーまたはロールに関連するエンティティの作成が必要になることがあります。 これは、手順 2 で作成した各 テーブルとアプリケーション データ テーブルとの間に外部キー制約を確立するとき、SqlMembershipProviderSqlRoleProvider スキーマに関して情報を得るのに役立ちます。 さらに言うと、まれな状況においては、データベース レベルでユーザー ストアとロール ストアに (Membership または Roles クラス経由ではなく) 直接インターフェイスを作成する必要性が生じることがあります。

アプリケーション内でのユーザー ストアのパーティション分割

メンバーシップとロールのフレームワークは、1 つのユーザーとロール ストアを、異なるアプリケーション間で共有できるように設計されています。 メンバーシップまたはロールのフレームワークを使用する ASP.NET アプリケーションでは、使用するアプリケーション パーティションを指定する必要があります。 つまり、複数の Web アプリケーションが、同じユーザー ストアとロール ストアを使用できます。 図 11 は、HRSite、CustomerSite、SalesSite の 3 つのアプリケーションにパーティション分割された、ユーザー ストアとロール ストアを示しています。 これら 3 つの Web アプリケーションは、それぞれ独自かつ一意のユーザーとロールを持ちますが、すべてが同じデータベース テーブルにユーザー アカウントとロール情報を物理的に保存しています。

User Accounts May Be Partitioned Across Multiple Applications

図 11: ユーザー アカウントは複数のアプリケーション間でパーティション分割できる (クリックするとフルサイズの画像が表示されます)

aspnet_Applications テーブルが、これらのパーティションを定義しています。 データベースを使用してユーザー アカウント情報を保存する各アプリケーションが、このテーブルの行に表されています。 aspnet_Applications テーブルには、ApplicationIdApplicationNameLoweredApplicationNameDescription の 4 つの列があります。ApplicationId の型は uniqueidentifier であり、これがテーブルの主キーです。ApplicationName は、アプリケーションごとに一意のわかりやすい名前を指定します。

メンバーシップとロールに関連する他のテーブルからは、aspnet_ApplicationsApplicationId フィールドにリンクが返されています。 たとえば、各ユーザー アカウントのレコードを含む aspnet_Users テーブルには、ApplicationId の外部キー フィールドがあります (aspnet_Roles についても同様)。 これらのテーブルの ApplicationId フィールドは、ユーザー アカウントまたはロールが属するアプリケーション パーティションを指定します。

ユーザー アカウント情報の保存

ユーザー アカウント情報は、2 つのテーブル、aspnet_Users および aspnet_Membership に保存されます。 aspnet_Users テーブルには、重要なユーザー アカウント情報を保持するフィールドが含まれています。 最も関連性のある列は次の 3 つです。

  • UserId
  • UserName
  • ApplicationId

UserId は (型が uniqueidentifier の) 主キーです。 UserName は型が nvarchar(256) で、パスワードと共にユーザーの資格情報を構成します (ユーザーのパスワードは aspnet_Membership テーブルに保存されます)。ApplicationId は、aspnet_Applications 内のアプリケーションにユーザー アカウントをリンクします。 UserNameApplicationId 列には複合的な UNIQUE 制約があります。 これにより、特定のアプリケーションの中の各 UserName は一意になりますが、異なるアプリケーションでは、同じ UserName を使用できるようになります。

aspnet_Membership テーブルには、ユーザーのパスワード、メール アドレス、最後のログイン日時など、その他のユーザー アカウント情報が含まれています。 aspnet_Users 内のレコードと aspnet_Membership テーブルの間は、1 対 1 で対応しています。 このリレーションシップは、aspnet_MembershipUserId フィールドによって保証され、これがテーブルの主キーとして機能します。 aspnet_Users テーブルと同様に、aspnet_Membership にも、この情報を特定のアプリケーション パーティションに紐付けるための ApplicationId フィールドが含まれています。

パスワードの保護

パスワードの情報は aspnet_Membership テーブルに保存されます。 SqlMembershipProvider を使用すると、次の 3 つの手法のいずれかを使用して、データベースにパスワードを保存できます。

  • クリア - パスワードはプレーンテキストとしてデータベースに保存されます。 このオプションは、使用しないことを強くお勧めします。 データベースが (バックドアを見つけたハッカーや、不満を持ちデータベースのアクセス権がある従業員などにより) 侵害された場合は、すべてのユーザーの資格情報が簡単に盗まれます。
  • ハッシュ化 - パスワードは、一方向ハッシュ アルゴリズムとランダムに生成されたソルト値を使用して、ハッシュ化されます。 このハッシュ値は (ソルトと共に) データベースに保存されます。
  • 暗号化 - 暗号化されたバージョンのパスワードがデータベースに保存されます。

使用されるパスワード ストレージの手法は、Web.config で指定された SqlMembershipProvider 設定に応じて変わります。 SqlMembershipProvider の設定をカスタマイズする方法については、手順 4 で見ていきます。 既定の動作では、パスワードのハッシュを保存します。

パスワードの保存先である列は PasswordPasswordFormatPasswordSalt です。 PasswordFormat は、パスワードの保存に使用される手法を示す int 型の値を持つフィールドで、クリアの場合は 0、ハッシュ化の場合は 1、暗号化の場合は 2 です。 PasswordSalt には、パスワードの保存に使用される手法に関係なく、ランダムに生成された文字列が割り当てられます。PasswordSalt の値は、パスワードのハッシュを計算する場合にのみ使用されます。 最後に、Password 列には実際のパスワード データ (プレーンテキストのパスワード、パスワードのハッシュ、暗号化されたパスワード) が含まれます。

表 1 は、パスワード MySecret! を保存する際のさまざまなストレージ手法に対し、これら 3 つの列がどのようになるかを示しています 。

Storage Technique<_o3a_p /> Password<_o3a_p /> PasswordFormat<_o3a_p /> PasswordSalt<_o3a_p />
Clear MySecret! 0 tTnkPlesqissc2y2SMEygA==
ハッシュ 2oXm6sZHWbTHFgjgkGQsc2Ec9ZM= 1 wFgjUfhdUFOCKQiI61vtiQ==
Encrypted 62RZgDvhxykkqsMchZ0Yly7HS6onhpaoCYaRxV8g0F4CW56OXUU3e7Inza9j9BKp 2 LSRzhGS/aa/oqAXGLHJNBw==

表 1: パスワード MySecret! を保存する場合のパスワード関連フィールドの値の例

Note

SqlMembershipProvider によって使用される、特定の暗号化アルゴリズムまたはハッシュ アルゴリズムは、<machineKey> 要素での設定によって決まります。

ロールとロールの関連付けの保存

ロール フレームワークを使用すると、開発者はロールのセットを定義し、どのユーザーがどのロールに属するかを指定できます。 この情報は、2 つのテーブル (aspnet_Roles および aspnet_UsersInRoles) を介してデータベースにキャプチャされます。 aspnet_Roles テーブル内の各レコードは、特定のアプリケーションのロールを表します。 aspnet_Users テーブルと同様に、この aspnet_Roles テーブルは、ここでの説明に関連する 3 つの列を持っています。

  • RoleId
  • RoleName
  • ApplicationId

RoleId は (型が uniqueidentifier の) 主キーです。 RoleNamenvarchar(256) 型です。 そして ApplicationId は、ユーザー アカウントを aspnet_Applications 内の特定のアプリケーションにリンクします。 RoleName および ApplicationId 列には複合的な UNIQUE 制約があり、特定のアプリケーションの中で各ロール名が一意になることを保証しています。

aspnet_UsersInRoles テーブルは、ユーザーとロールの間でマッピングの機能を提供します。 存在する列は UserIdRoleId の 2 つのみで、これらがともに、複合的な主キーを構成します。

手順 4: プロバイダーを指定してその設定をカスタマイズする

メンバーシップ フレームワークやロール フレームワークなど、プロバイダー モデルをサポートするすべてのフレームワークには実装の詳細が含まれていないので、代わりに責任をプロバイダー クラスに委任します。 メンバーシップ フレームワークの場合、Membership クラスはユーザー アカウントを管理するための API を定義しますが、これがユーザー ストアと直接やり取りすることはありません。 むしろ、Membership クラスのメソッドは、構成されたプロバイダーに要求を渡すので、ここでは SqlMembershipProvider を使用しています。 Membership クラス内のいずれかのメソッドを呼び出す場合、メンバーシップ フレームワークは、この呼び出しを SqlMembershipProvider に委任することをどう認識するのでしょうか?

この Membership クラスには、登録済みのすべてのプロバイダー クラスへの参照を含む Providers プロパティがあり、メンバーシップ フレームワークが使用できます。 登録されたプロバイダーには、それぞれ名前と型が関連付けられています。 名前では、Providers コレクション内の特定のプロバイダーを参照するためのわかりやすい方法が提供され、型ではプロバイダーのクラスが識別されます。 さらに、登録されている各プロバイダーには、構成設定を含めることもできます。 メンバーシップ フレームワークの構成設定には、多くの他の設定とともに、PasswordFormatrequiresUniqueEmail が含まれています。 SqlMembershipProvider で使用される構成設定の完全なリストについては、表 2 を参照してください。

Providers プロパティの内容は、Web アプリケーションの構成設定を通じて指定されます。 既定では、すべての Web アプリケーションには、型が SqlMembershipProvider で名前が AspNetSqlMembershipProvider のプロバイダーがあります。 この既定のメンバーシップ プロバイダーは、machine.config に登録されています (場所は %WINDIR%\Microsoft.Net\Framework\v2.0.50727\CONFIG)。

<membership> 
 <providers>
 <add name="AspNetSqlMembershipProvider"
 type="System.Web.Security.SqlMembershipProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" 
 connectionStringName="LocalSqlServer"
 enablePasswordRetrieval="false"
 enablePasswordReset="true"
 requiresQuestionAndAnswer="true"
 applicationName="/"
 requiresUniqueEmail="false"
 passwordFormat="Hashed"
 maxInvalidPasswordAttempts="5"
 minRequiredPasswordLength="7"
 minRequiredNonalphanumericCharacters="1"
 passwordAttemptWindow="10"
 passwordStrengthRegularExpression=""/>
 </providers> 
</membership>

上のマークアップが示すように、<membership> 要素はメンバーシップ フレームワークの構成設定を定義する一方、子要素 <providers>は登録済みのプロバイダーを指定します。 プロバイダーは、<add> または <remove> 要素を使用して追加または削除できます。現在登録されているすべてのプロバイダーを削除するには、<clear> 要素を使用します。 上のマークアップに示すように、machine.config は、型が SqlMembershipProvider で名前が AspNetSqlMembershipProvider のプロバイダーを追加します。

name および type 属性に加えて、<add> 要素には、さまざまな構成設定に対して値を定義する属性が含まれています。 表 2 に、SqlMembershipProvider に固有の使用可能な構成設定と、それぞれの説明を示します。

Note

表 2 に示されている既定値は、SqlMembershipProvider クラスで定義されている既定値を参照します。 AspNetSqlMembershipProvider の中のすべての構成設定が、SqlMembershipProvider クラスの既定値に対応しているわけではないことに注意してください。 たとえば、メンバーシップ プロバイダーで指定されていなければ、requiresUniqueEmail 設定の既定値は true になります。 ただし、false 値を明示的に指定することで、AspNetSqlMembershipProvider がこの既定値をオーバーライドします。

Setting<_o3a_p /> Description<_o3a_p />
ApplicationName メンバーシップ フレームワークを使用すると、1 つのユーザー ストアを複数のアプリケーション間でパーティション分割できることを思い出してください。 この設定は、メンバーシップ プロバイダーが使用するアプリケーション パーティションの名前を示します。 この値が明示的に指定されていない場合は、実行時に、アプリケーションの仮想ルート パスの値に設定されます。
commandTimeout SQL コマンドのタイムアウト値 (秒単位) を指定します。 既定値は 30 です。
connectionStringName ユーザー ストア データベースへの接続に使用する、<connectionStrings> 要素内の接続文字列の名前。 この値は必須です。
description 登録済みプロバイダーのわかりやすい説明を提供します。
enablePasswordRetrieval ユーザーが忘れたパスワードを取得できるかどうかを指定します。 既定値は false です。
enablePasswordReset ユーザーが自分のパスワードをリセットできるかどうかを示します。 既定値は true です。
maxInvalidPasswordAttempts ユーザーがロックアウトされる前に、指定された passwordAttemptWindow の中でユーザーが試行できるログインの失敗の最大回数。既定値は 5 です。
minRequiredNonalphanumericCharacters ユーザーのパスワードに含める必要がある、英数字以外の文字の最小数。 この値は 0 から 128 の間である必要があります。既定値は 1 です。
minRequiredPasswordLength パスワードに必要な最小文字数。 この値は 0 から 128 の間である必要があります。既定値は 7 です。
name 登録済みプロバイダーの名前。 この値は必須です。
passwordAttemptWindow 失敗したログインの試行が追跡される分数。 ユーザーが、この指定されたウィンドウ内に無効なログイン資格情報を maxInvalidPasswordAttempts 回指定した場合、そのユーザーはロックアウトされます。既定値は 10 です。
PasswordFormat パスワード ストレージの形式: ClearHashed、または Encrypted。 既定値は、Hashed です。
passwordStrengthRegularExpression 指定した場合、この正規表現は、新しいアカウントの作成かパスワードの変更時に、ユーザーが選択したパスワードの強度を評価するために使用されます。 既定値は空の文字列です。
requiresQuestionAndAnswer ユーザーが自分のパスワードを取得またはリセットする場合に、セキュリティの質問に回答する必要があるかどうかを指定します。 既定値は true です。
requiresUniqueEmail 特定のアプリケーション パーティション内のすべてのユーザー アカウントに、一意のメール アドレスが要求されるかどうかを示します。 既定値は true です。
type プロバイダーの種類を指定します。 この値は必須です。

表 2: メンバーシップと SqlMembershipProvider の構成設定

AspNetSqlMembershipProvider に加えて、同様のマークアップを Web.config ファイルに追加することで、アプリケーションごとに他のメンバーシップ プロバイダーを登録できます。

Note

ロール フレームワークの機能もほぼ同様で、machine.config には既定の登録済みロール プロバイダーがあり、登録されたプロバイダーは、Web.config の中でアプリケーションごとにカスタマイズできます。 今後のチュートリアルでは、ロール フレームワークとその構成マークアップについて詳しく説明します。

SqlMembershipProvider の設定のカスタマイズ

既定の SqlMembershipProvider (AspNetSqlMembershipProvider) の connectionStringName 属性は、LocalSqlServer に設定されています。 AspNetSqlMembershipProvider プロバイダーと同様に、接続文字列名 LocalSqlServermachine.config で定義されます。

<connectionStrings> 
 <add name="LocalSqlServer" 
 connectionString="data source=.\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|aspnetdb.mdf;User Instance=true" 
 providerName="System.Data.SqlClient"/> 
</connectionStrings>

ご覧のとおり、この接続文字列では、|DataDirectory|aspnetdb.mdf にある SQL 2005 Express Edition データベースが定義されています。 文字列 |DataDirectory| は、~/App_Data/ ディレクトリを指すために実行時に変換されるため、データベース パス |DataDirectory|aspnetdb.mdf は ~/App_Data/aspnet.mdf に変換されます。

アプリケーションの Web.config ファイルにメンバーシップ プロバイダー情報を指定していない場合、アプリケーションは既定の登録済みメンバーシップ プロバイダー (AspNetSqlMembershipProvider) を使用します。 ~/App_Data/aspnet.mdf データベースが存在しない場合には、ASP.NET ランタイムで自動的に作成され、さらにアプリケーション サービス スキーマが追加されます。 ただし、ここでは aspnet.mdf データベースは使用しません。代わりに、手順 2 で作成した SecurityTutorials.mdf データベースを使用します。 この変更は、次の 2 つの方法のいずれかで行うことができます。

  • Web.configで接続文字列名LocalSqlServerの値を指定しますWeb.config で接続文字列名の値 LocalSqlServer を上書きすることで、既定の登録済みメンバーシップ プロバイダー (AspNetSqlMembershipProvider) を使用し、これを SecurityTutorials.mdf データベースと正しく連携させることができます。 AspNetSqlMembershipProvider で指定されている構成設定に満足している場合、この方法で問題ありません。 この手法の詳細については、Scott Guthrie 氏のブログ投稿、「ASP.NET 2.0 Application Services を構成して SQL Server 2000 または SQL Server 2005 を使用する」を参照してください。
  • 型が SqlMembershipProvider の新しい登録済みプロバイダーを追加し、その connectionStringName 設定を、SecurityTutorials.mdf データベースを指すように構成します。このアプローチは、データベース接続文字列に加えて、他の構成プロパティをカスタマイズする場合に便利です。 私自身のプロジェクトでは、柔軟性と読みやすさのために、常にこのアプローチを使用しています。

SecurityTutorials.mdf データベースを参照する新しい登録済みプロバイダーを追加する前に、Web.config<connectionStrings> セクションに適切な接続文字列値を追加する必要があります。 次のマークアップは、App_Data フォルダー内にある SQL Server 2005 Express Edition の SecurityTutorials.mdf データベースを参照する、SecurityTutorialsConnectionString という名前の新しい接続文字列を追加します。

<configuration>
 <connectionStrings>
 <add name="SecurityTutorialsConnectionString" 
 connectionString="Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\SecurityTutorials.mdf;Integrated Security=True;User Instance=True" 
 providerName="System.Data.SqlClient"/>
 </connectionStrings> 
 <system.web>
 ... Configuration markup removed for brevity ...  </system.web>
</configuration>

Note

代替のデータベース ファイルを使用している場合は、必要に応じて接続文字列を更新します。 適切な接続文字列の形成の詳細については、ConnectionStrings.com を参照してください。

次に、下記のメンバーシップ構成マークアップを Web.config ファイルに追加します。 このマークアップでは、SecurityTutorialsSqlMembershipProvider という名前の新しいプロバイダーが登録されます。

<configuration>
 <connectionStrings>
 <add name="SecurityTutorialsConnectionString" 
 connectionString="Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\SecurityTutorials.mdf;Integrated Security=True;User Instance=True" 
 providerName="System.Data.SqlClient"/>
 </connectionStrings> 
 <system.web>
 <membership defaultProvider="SecurityTutorialsSqlMembershipProvider">
 <providers>
 <!-- Add a customized SqlMembershipProvider --> 
 <add name="SecurityTutorialsSqlMembershipProvider" 
 type="System.Web.Security.SqlMembershipProvider"
 connectionStringName="SecurityTutorialsConnectionString"
 enablePasswordRetrieval="false"
 enablePasswordReset="true"
 requiresQuestionAndAnswer="true"
 applicationName="SecurityTutorials"
 requiresUniqueEmail="true"
 passwordFormat="Hashed"
 maxInvalidPasswordAttempts="5"
 minRequiredPasswordLength="7"
 minRequiredNonalphanumericCharacters="1"
 passwordAttemptWindow="10"
 passwordStrengthRegularExpression=""/>
 </providers>
 </membership>
 ... Configuration markup removed for brevity ... 
 </system.web>
</configuration>

SecurityTutorialsSqlMembershipProvider プロバイダーの登録に加えて、上記のマークアップでは、既定のプロバイダーとして (<membership> 要素内の defaultProvider 属性を介して) SecurityTutorialsSqlMembershipProvider を定義します。 メンバーシップ フレームワークには、複数の登録済みプロバイダーを含めることができることを思い出してください。 AspNetSqlMembershipProvider は、machine.config で最初のプロバイダーとして登録されているため、特に指定しない限り、これが既定のプロバイダーとして機能します。

現在、このアプリケーションには、2 つの登録済みプロバイダー (AspNetSqlMembershipProvider および SecurityTutorialsSqlMembershipProvider) が含まれています。 ただし、SecurityTutorialsSqlMembershipProvider プロバイダーを登録する前に、<add> 要素の直前に <clear /> 要素を追加することで、以前に登録されたすべてのプロバイダーをクリアしておくこともできます。 これにより、登録済みプロバイダーのリストから AspNetSqlMembershipProvider がクリアされます。つまり、SecurityTutorialsSqlMembershipProvider が唯一の登録されているメンバーシップ プロバイダーになります。 この方法を使用した場合は、SecurityTutorialsSqlMembershipProvider を既定のプロバイダーとしてマークする必要はありません。これが、唯一の登録されているメンバーシップ プロバイダーとなるためです。 <clear /> の使用の詳細については、「プロバイダーの追加時の <clear /> の使用」を参照してください。

SecurityTutorialsSqlMembershipProviderconnectionStringName 設定は、ここで追加された SecurityTutorialsConnectionString 接続文字列の名前を参照し、その applicationName 設定の値が SecurityTutorials に設定されていることに注意してください。 さらに、requiresUniqueEmail 設定は true に設定されています。 その他のすべての構成オプションは、AspNetSqlMembershipProvider の値と同じです。 必要に応じて、ここでの構成は自由に変更してください。 たとえば、英数字以外の必要な文字を 1 文字ではなく 2 文字にする、あるいはパスワードの長さを 7 文字ではなく 8 文字に増やすことで、パスワードの強度を強化できます。

Note

メンバーシップ フレームワークを使用すると、1 つのユーザー ストアを複数のアプリケーション間でパーティション分割できることを思い出してください。 メンバーシップ プロバイダーの applicationName 設定は、ユーザー ストアと連携する場合に、どのアプリケーションをプロバイダーが使用するのかを示します。 applicationName 構成設定の値を、明示的に設定することは重要です。applicationName が明示的に設定されていない場合、実行時にこれが Web アプリケーションの仮想ルート パスに割り当てられるためです。 これは、アプリケーションの仮想ルート パスが変更されない限り正常に動作しますが、アプリケーションを別のパスに移動した場合には、applicationName 設定も変更されます。 これが起きると、メンバーシップ プロバイダーは、以前に使用したものとは異なるアプリケーション パーティションを操作するようになります。 移動前に作成されたユーザー アカウントは別のアプリケーション パーティションに存在することとなり、それらのユーザーはサイトにログインできなくなります。 この問題の詳細については、「ASP.NET 2.0 メンバーシップとその他のプロバイダーを構成するときに常に applicationName プロパティを設定する」を参照してください。

まとめ

この時点で、アプリケーション サービス (SecurityTutorials.mdf) が構成されたデータベースがあり、Web アプリケーションの構成を終えています。つまり、メンバーシップ フレームワークは、ここで登録した SecurityTutorialsSqlMembershipProvider プロバイダーを使用するようになっています。 この登録済みプロバイダーの型は SqlMembershipProvider で、connectionStringName は適切な接続文字列 (SecurityTutorialsConnectionString) に設定されており、applicationName 値が明示的に設定されています。

この段階で、アプリケーションからメンバーシップ フレームワークを使用する準備ができています。 次のチュートリアルでは、新しいユーザー アカウントを作成する方法について説明します。 その後、ユーザーの認証、ユーザー ベースの認可の実行、追加のユーザー関連情報のデータベースへの保存について見ていきます。

プログラミングに満足!

もっと読む

この記事で説明したトピックの詳細については、次のリソースを参照してください。

このチュートリアルに含まれるトピックに関するビデオ トレーニング

作成者について

複数の ASP/ASP.NET 書籍の著者であり、4GuysFromRolla.com の創設者である Scott Mitchell は、1998 年から Microsoft Web テクノロジに取り組んでいます。 Scott は、独立したコンサルタント、トレーナー、ライターとして働いています。 彼の最新の本は サムズは24時間で2.0 ASP.NET 自分自身を教えています。 Scott には、mitchell@4guysfromrolla.com または http://ScottOnWriting.NET のブログを介して連絡できます。

特別な感謝

このチュートリアル シリーズは、多くの役に立つ校閲者によってレビューされました。 このチュートリアルのリード レビュー担当者は、Alicja Maziarz でした。 今後の MSDN の記事を確認することに関心がありますか? その場合は、mitchell@4GuysFromRolla.com までご一報ください。