ロールベースの承認 (C#)

作成者: Scott Mitchell

Note

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

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

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

このチュートリアルでは、まず Roles フレームワークでユーザーのロールをそのユーザーのセキュリティ コンテキストに関連付ける方法について説明します。 次に、ロール ベースの URL 認可規則を適用する方法について調べます。 その後、表示されるデータや ASP.NET ページで提供される機能を変更するための宣言型の方法とプログラムによる方法の使用について説明します。

はじめに

ユーザー ベースの認可」のチュートリアルでは、URL 認可を使用して、特定の一連のページにアクセスできるユーザーを指定する方法について説明しました。 Web.config 内のほんの少しのマークアップを使用して、認証されたユーザーだけがページにアクセスできるようにするよう ASP.NET に指示することができました。 あるいは、ユーザー Tito と Bob だけが許可されるように規定したり、Sam を除くすべての認証されたユーザーが許可されるように指定したりすることができました。

URL 認可に加えて、アクセスしているユーザーに基づいて、表示されるデータやページで提供される機能を制御するための宣言型の方法とプログラムによる方法についても説明しました。 特に、現在のディレクトリの内容を一覧表示するページを作成しました。 このページには誰でもアクセスできますが、認証されたユーザーだけがファイルの内容を表示でき、Tito だけがファイルを削除できました。

認可規則をユーザーごとに適用すると、ブックキーピングが非常に面倒になる場合があります。 より保守しやすいアプローチは、ロール ベースの認可を使用することです。 幸いなことに、認可規則を適用するために自由に使用できるツールは、ロールに対してもユーザー アカウントに対する場合と同様に適切に機能します。 URL 認可規則では、ユーザーの代わりにロールを指定できます。 認証されたユーザーと匿名ユーザーに対して異なる出力をレンダリングする LoginView コントロールは、ログインしているユーザーのロールに基づいて異なるコンテンツ表示するように構成できます。 また、Roles API には、ログインしているユーザーのロールを特定するためのメソッドが含まれています。

このチュートリアルでは、まず Roles フレームワークでユーザーのロールをそのユーザーのセキュリティ コンテキストに関連付ける方法について説明します。 次に、ロール ベースの URL 認可規則を適用する方法について調べます。 その後、表示されるデータや ASP.NET ページで提供される機能を変更するための宣言型の方法とプログラムによる方法の使用について説明します。 それでは始めましょう。

ロールがユーザーのセキュリティ コンテキストに関連付けられる方法の理解

要求は、ASP.NET パイプラインに入力されるたびに、要求元を識別する情報が含まれているセキュリティ コンテキストに関連付けられます。 フォーム認証を使用している場合は、ID トークンとして認証チケットが使用されます。 「フォーム認証の概要」のチュートリアルで説明したように、FormsAuthenticationModule は要求元の ID を特定する役割を果たします。これは、AuthenticateRequest イベント中に実行されます。

有効期限が切れていない有効な認証チケットが見つかった場合、FormsAuthenticationModule は、それをデコードして要求元の ID を確認します。 新しい GenericPrincipal オブジェクトを作成し、これを HttpContext.User オブジェクトに割り当てます。 プリンシパル (GenericPrincipal など) の目的は、認証されたユーザーの名前とそのユーザーが属しているロールを識別することです。 この目的は、すべてのプリンシパル オブジェクトに Identity プロパティと IsInRole(roleName) メソッドがあるという事実により明らかです。 ただし、FormsAuthenticationModule ではロール情報の記録は行われず、それによって作成される GenericPrincipal オブジェクトでもロールは指定されません。

Roles フレームワークが有効になっている場合は、RoleManagerModule HTTP モジュールが FormsAuthenticationModule の後にステップ インし、認証されたユーザーのロールを AuthenticateRequest イベントの後に発生する PostAuthenticateRequest イベント中に識別します。 その要求が認証されたユーザーからのものである場合、RoleManagerModuleFormsAuthenticationModule によって作成された GenericPrincipal オブジェクトを上書きし、それを RolePrincipal オブジェクトに置き換えます。 RolePrincipal クラスは Roles API を使用して、そのユーザーが属しているロールを特定します。

図 1 は、フォーム認証と Roles フレームワークを使用しているときの ASP.NET パイプライン ワークフローを示しています。 最初に FormsAuthenticationModule が実行され、そのユーザーの認証チケットを使用してユーザーを識別し、新しい GenericPrincipal オブジェクトを作成します。 次に、RoleManagerModule がステップ インし、GenericPrincipal オブジェクトを RolePrincipal オブジェクトで上書きします。

匿名ユーザーがサイトにアクセスした場合は、FormsAuthenticationModuleRoleManagerModule もプリンシパル オブジェクトを作成しません。

The ASP.NET Pipeline Events for an Authenticated User When Using Forms Authentication and the Roles Framework

図 1: フォーム認証と Roles フレームワークを使用しているときの認証されたユーザーのための ASP.NET パイプライン イベント (クリックするとフルサイズの画像が表示されます)

RolePrincipal オブジェクトの IsInRole(roleName) メソッドは、Roles.GetRolesForUser を呼び出してユーザーのロールを取得することにより、そのユーザーが roleName のメンバーであるかどうかを判定します。 SqlRoleProvider を使用している場合は、これにより、ロール ストア データベースへのクエリが生成されます。 ロール ベースの URL 認可規則を使用している場合、RolePrincipalIsInRole メソッドは、ロール ベースの URL 認可規則によって保護されているページへの要求が発生するたびに呼び出されます。 要求のたびにデータベース内のロール情報を検索しなくても済むように、ロール フレームワークには、ユーザーのロールを Cookie にキャッシュするオプションが含まれています。

Roles フレームワークがユーザーのロールを Cookie にキャッシュするように構成されている場合、RoleManagerModule は、ASP.NET パイプラインの EndRequest イベント中に Cookie を作成します。 この Cookie は、それ以降の要求の、RolePrincipal オブジェクトが作成される PostAuthenticateRequest で使用されます。 Cookie が有効で、かつ有効期限が切れていない場合は、Cookie 内のデータが解析され、ユーザーのロールを設定するために使用されます。これにより、RolePrincipal は、ユーザーのロールを特定するために Roles クラスを呼び出す必要がなくなります。 図 2 は、このワークフローを示しています。

The User's Role Information Can Be Stored in a Cookie to Improve Performance

図 2: ユーザーのロール情報を Cookie に格納してパフォーマンスを向上させることができる (クリックするとフルサイズの画像が表示されます)

既定では、ロール キャッシュ Cookie のメカニズムは無効になっています。 これは、Web.config 内の <roleManager>; 構成マークアップを使用して有効にすることができます。 <roleManager> 要素を使用したロール プロバイダーの指定については「ロールの作成と管理」のチュートリアルで説明したため、アプリケーションの Web.config ファイルにはこの要素が既に含まれているはずです。 ロール キャッシュ Cookie の設定は <roleManager>; 要素の属性として指定され、表 1 にまとめられています。

Note

表 1 に一覧表示されている構成設定は、結果として得られるロール キャッシュ Cookie のプロパティを示しています。 Cookie と、そのしくみ、さまざまなプロパティの詳細については、この Cookie のチュートリアルを参照してください。

プロパティ 説明
cacheRolesInCookie Cookie のキャッシュが使用されているかどうかを示すブール値。 既定値は false です。
cookieName ロール キャッシュ Cookie の名前。 既定値は ".ASPXROLES" です。
cookiePath ロール名の Cookie のパス。 パス属性を使用すると、開発者は Cookie のスコープを特定のディレクトリ階層に制限できます。 既定値は "/" です。これは、そのドメインに対して行われたすべての要求に認証チケット Cookie を送信するようブラウザーに通知します。
cookieProtection ロール キャッシュ Cookie を保護するためにどのような手法が使用されるかを示します。 許容される値は、All (既定値)、EncryptionNoneValidation です。
cookieRequireSSL 認証 Cookie を送信するために SSL 接続が必要かどうかを示すブール値。 既定値は false です。
cookieSlidingExpiration ユーザーが 1 回のセッション中にサイトにアクセスするたびに Cookie のタイムアウトがリセットされるかどうかを示すブール値。 既定値は false です。 この値は、createPersistentCookietrue に設定されている場合のみ関連します。
cookieTimeout 認証チケット Cookie の有効期限が切れる時間を分単位で指定します。 既定値は 30 です。 この値は、createPersistentCookietrue に設定されている場合のみ関連します。
createPersistentCookie ロール キャッシュ Cookie がセッション Cookie か永続 Cookie かを指定するブール値。 false (既定値) の場合、セッション Cookie が使用され、ブラウザーが閉じられると削除されます。 true である場合、永続 Cookie が使用されると、cookieSlidingExpiration の値に応じて、作成後または前回のアクセス後の cookieTimeout の時間 (分) の有効期限が切れます。
domain Cookie のドメイン値を指定します。 既定値は空の文字列です。これにより、ブラウザーは発行元からのドメイン (www.yourdomain.com など) に使用されます。 この場合、admin.yourdomain.com などのサブドメインに要求を行うときに Cookie は送信されません。 Cookie をすべてのサブドメインに渡す場合は domain 属性をカスタマイズ、それを "yourdomain.com" に設定する必要があります。
maxCachedResults Cookie にキャッシュされるロール名の最大数を指定します。 既定値は 25 です。 RoleManagerModule では、maxCachedResults 以上のロールに属するユーザーの Cookie は作成されません。 その結果、RolePrincipal オブジェクトの IsInRole メソッドは Roles クラスを使用してユーザーのロールを決定します。 多くのユーザー エージェントが 4,096 バイトを超える Cookie を許可していないため、maxCachedResults が存在します。 そのため、この上限は、このサイズ制限を超える可能性を軽減することを目的とします。 ロール名が非常に長い場合は、より小さな maxCachedResults 値を指定することを検討する必要がある場合があります。逆に、ロール名が非常に短い場合は、この値を増やすことができる可能性があります。

表 1: ロール キャッシュ Cookie の構成オプション

非永続的なロール キャッシュ Cookie を使用するようにアプリケーションを構成しましょう。 これを実現するには、Web.config 内の <roleManager> 要素を次の cookie 関連の属性が含まれるように更新します。

<roleManager enabled="true"    
          defaultProvider="SecurityTutorialsSqlRoleProvider"    
          cacheRolesInCookie="true"    
          createPersistentCookie="false"    
          cookieProtection="All">    

     <providers>    
     ...    
     </providers>    
</roleManager>

ここでは、cacheRolesInCookiecreatePersistentCookiecookieProtection の 3 つの属性を追加することによって <roleManager> 要素を更新しました。 cacheRolesInCookietrue に設定することにより、RoleManagerModule はユーザーのロールを自動的に Cookie にキャッシュするようになり、要求のたびにユーザーのロール情報を検索しなくても済みます。 また、createPersistentCookie および cookieProtection 属性をそれぞれ falseAll に明示的に設定しました。 技術的には、これらの属性は既定値に割り当てたばかりであるため、それらの値を指定する必要はなかったのですが、永続的な Cookie を使用しておらず、この Cookie には暗号化と検証の両方が行われていることを明示的に明らかにするために、ここに配置しました。

これですべて完了です。 この後、Roles フレームワークによってユーザーのロールが Cookie にキャッシュされます。 ユーザーのブラウザーが Cookie をサポートしていなかったり、Cookie が何らかの理由で削除されたり、失われたりしていても大きな問題ではありません。Cookie が使用できない (または、無効か、有効期限が切れている) 場合、RolePrincipal オブジェクトは単純に Roles クラスを使用します。

Note

Microsoft の Patterns & Practices グループは、永続的なロール キャッシュ Cookie の使用をお勧めしません。 ロール メンバーシップを証明するにはロール キャッシュ Cookie を所有するだけで十分であるため、ハッカーが有効なユーザーの Cookie へのアクセス権を何らかの方法で取得できた場合は、そのユーザーを偽装できます。 Cookie がユーザーのブラウザー上に永続化されていると、これが発生する可能性が高くなります。 このセキュリティに関する推奨事項やその他のセキュリティ上の問題の詳細については、ASP.NET 2.0 のセキュリティに関する質問の一覧に関するページを参照してください。

手順 1: ロール ベースの URL 認可規則の定義

ユーザー ベースの認可」のチュートリアルで説明したように、URL 認可は、ユーザーまたはロールごとに一連のページへのアクセスを制限するための手段を提供します。 URL 認可規則は、Web.config 内で <allow><deny> の子要素を含む <authorization> 要素を使用して指定されます。 前のチュートリアルで説明したユーザー関連の認可規則に加えて、<allow><deny> の各子要素には、次のものも含めることができます。

  • 特定のロール
  • ロールのコンマ区切りリスト

たとえば、URL 認可規則では、管理者およびスーパーバイザー ロールのユーザーにはアクセス権を付与するが、その他のすべてのユーザーにはアクセス権を拒否することができます。

<authorization>
     <allow roles="Administrators, Supervisors" />
     <deny users="*" />
</authorization>

上記のマークアップ内の <allow> 要素は管理者およびスーパーバイザー ロールが許可されることを、<deny>; 要素は "すべての" ユーザーが拒否されることを示しています。

ManageRoles.aspxUsersAndRoles.aspxCreateUserWizardWithRoles.aspx の各ページが管理者ロールのユーザーからしかアクセスできないのに対して、RoleBasedAuthorization.aspx ページはすべてのビジターからアクセス可能のままになるようにアプリケーションを構成しましょう。

これを実現するには、まず Roles フォルダーに Web.config ファイルを追加します。

Add a Web.config File to the Roles directory

図 3: Roles ディレクトリに Web.config ファイルを追加する (クリックするとフルサイズの画像が表示されます)

次に、Web.config に次の構成マークアップを追加します。

<?xml version="1.0"?>    

<configuration>    
     <system.web>    
          <authorization>    
               <allow roles="Administrators" />    
               <deny users="*"/>    
          </authorization>    

     </system.web>

     <!-- Allow all users to visit RoleBasedAuthorization.aspx -->    
     <location path="RoleBasedAuthorization.aspx">    
          <system.web>    
               <authorization>    
                    <allow users="*" />    

               </authorization>    
          </system.web>    
     </location>    
</configuration>

<system.web> セクション内の <authorization> 要素は、Roles ディレクトリ内の ASP.NET リソースには管理者ロールのユーザーしかアクセスできないことを示します。 <location> 要素は、RoleBasedAuthorization.aspx ページに対する一連の代替の URL 認可規則を定義し、すべてのユーザーがこのページにアクセスできるようにします。

Web.config への変更内容を保存したら、管理者ロールに属していないユーザーとしてログインし、保護されたページのいずれかにアクセスしてみてください。 UrlAuthorizationModule は、要求されたリソースにアクセスするためのアクセス許可を持っていないことを検出し、それにより FormsAuthenticationModule によってログイン ページにリダイレクトされます。 その後、ログイン ページによって UnauthorizedAccess.aspx ページ (図 4 を参照) にリダイレクトされます。 このログイン ページから UnauthorizedAccess.aspx への最後のリダイレクトは、「ユーザー ベースの認可」のチュートリアルの手順 2 でログイン ページに追加したコードのために発生します。 特に、クエリ文字列に ReturnUrl パラメーターが含まれている場合、このパラメーターは、ユーザーが表示を認可されていないページを表示しようとした後にログイン ページに到達したことを示すため、ログイン ページにより、すべての認証されたユーザーが自動的に UnauthorizedAccess.aspx にリダイレクトされます。

Only Users in the Administrators Role Can View the Protected Pages

図 4: 保護されたページは管理者ロールのユーザーしか表示できない (クリックするとフルサイズの画像が表示されます)

ログオフしてから、管理者ロールに属しているユーザーとしてログインします。 今度は、3 つの保護されたページを表示できるはずです。

Tito Can Visit the UsersAndRoles.aspx Page Because He is in the Administrators Role

図 5: Tito は管理者ロールに属しているため UsersAndRoles.aspx ページにアクセスできる (クリックするとフルサイズの画像が表示されます)

Note

URL 認可規則を (ロールまたはユーザーごとに) 指定する場合は、それらの規則が一番上から下に 1 つずつ分析される点に注意することが重要です。 一致が見つかるとすぐに、一致が <allow> または <deny> のどちらの要素で見つかったかに応じて、そのユーザーにアクセス権が付与または拒否されます。 一致が見つからなかった場合は、そのユーザーにアクセス権が付与されます。 そのため、アクセスを 1 つ以上のユーザー アカウントに制限したい場合は、必ず URL 認可構成内の最後の要素として <deny> 要素を使用する必要があります。 URL 認可規則に <deny> 要素が含まれていない場合は、すべてのユーザーにアクセス権が付与されます。URL 認可規則が分析される方法の詳細については、「ユーザー ベースの認可」のチュートリアルの UrlAuthorizationModule で認可規則を使用してアクセス権を付与または拒否する方法に関するセクションを参照し直してください。

手順 2: 現在ログインしているユーザーのロールに基づいた機能の制限

URL 認可により、特定のページ (または、あるフォルダーとそのサブフォルダー内のすべてのページ) の表示をどの ID が許可され、どの ID が拒否されるかを示す粗い認可規則を指定することが容易になります。 ただし、特定のケースでは、ページへのアクセスはすべてのユーザーに許可するが、アクセスしているユーザーのロールに基づいてページの機能を制限したい場合があります。 これには、ユーザーのロールに基づいてデータを表示または非表示にしたり、特定のロールに属しているユーザーに追加機能を提供したりすることか必要になる場合があります。

このようなきめ細かいロール ベースの認可規則は、宣言的にまたはプログラムで (あるいは、この 2 つの何らかの組み合わせを使用して) 実装できます。 次のセクションでは、LoginView コントロールを使用して、宣言型のきめ細かい認可を実装する方法について説明します。 その後、プログラムによる方法について調べます。 ただし、きめ細かい認可規則の適用を確認するには、最初に、アクセスしているユーザーのロールによって異なる機能を持つページを作成する必要があります。

システム内のすべてのユーザー アカウントを GridView に一覧表示するページを作成しましょう。 GridView には、各ユーザーのユーザー名、メール アドレス、最後のログイン日付、そのユーザーに関するコメントが含まれます。 各ユーザーの情報の表示に加えて、GridView には編集および削除機能が含まれます。 最初に、すべてのユーザーが編集および削除機能を使用できるようにこのページを作成します。 「LoginView コントロールの使用」と「プログラムによる機能の制限」のセクションでは、アクセスしているユーザーのロールに基づいて、これらの機能を有効または無効にする方法について説明します。

Note

作成しようとしている ASP.NET ページでは、GridView コントロールを使用してユーザー アカウントを表示します。 このチュートリアル シリーズでは、フォーム認証、認可、ユーザー アカウント、ロールに焦点を絞っているため、GridView コントロールの内側動作の説明にはあまり時間を費やしたくありません。 このチュートリアルでは、このページを設定するための具体的な詳しい手順を提供しますが、特定の選択が行われた理由や、特定のプロパティがレンダリングされる出力に与える影響の詳細については詳しく説明しません。 GridView コントロールの詳細な確認については、「ASP.NET 2.0 でのデータの操作」のチュートリアル シリーズを参照してください。

まず、Roles フォルダーの RoleBasedAuthorization.aspx ページを開きます。 GridView をこのページからデザイナーにドラッグし、その IDUserGrid に設定します。 しばらく待ってから Membership.GetAllUsers メソッドを呼び出し、結果の MembershipUserCollection オブジェクトを GridView にバインドするコードを記述します。 MembershipUserCollection には、システム内の各ユーザー アカウントの MembershipUser オブジェクトが含まれており、MembershipUser オブジェクトには UserNameEmailLastLoginDate などのプロパティがあります。

ユーザー アカウントをグリッドにバインドするコードを記述する前に、まず GridView のフィールドを定義しましょう。 GridView のスマート タグから、[列の編集] リンクをクリックして [フィールド] ダイアログ ボックスを起動します (図 6 を参照)。 ここから、左下隅にある [フィールドの自動生成] チェックボックスをオフにします。 この GridView には編集および削除機能を含めたいため、CommandField を追加し、その ShowEditButton および ShowDeleteButton プロパティを True に設定します。 次に、UserNameEmailLastLoginDateComment の各プロパティを表示するための 4 つのフィールドを追加します。 2 つの読み取り専用プロパティ (UserNameLastLoginDate) には BoundField を、2 つの編集可能フィールド (EmailComment) には TemplateField を使用します。

最初の BoundField に UserName プロパティを表示させ、その HeaderText および DataField プロパティを "UserName" に設定します。 このフィールドは編集可能にならないため、その ReadOnly プロパティを True に設定します。 LastLoginDate BoundField を、その HeaderText を "Last Login" に、その DataField を "LastLoginDate" に設定することによって構成します。 この BoundField の出力を (日付と時刻の代わりに) 日付だけが表示されるように書式設定しましょう。 これを実現するには、この BoundField の HtmlEncode プロパティを False に、その DataFormatString プロパティを "{0:d}" に設定します。 また、ReadOnly プロパティを True に設定します。

2 つの TemplateField の HeaderText プロパティを "Email" と "Comment" に設定します。

The GridView's Fields Can Be Configured Through the Fields Dialog Box

図 6: GridView のフィールドは [フィールド] ダイアログ ボックスで構成できる (クリックするとフルサイズの画像が表示されます)

次に、"Email" および "Comment" TemplateField の ItemTemplateEditItemTemplate を定義する必要があります。 それぞれの ItemTemplate に Label Web コントロールを追加し、Text プロパティを Email および Comment プロパティにそれぞれバインドします。

"Email" TemplateField の場合は、その EditItemTemplateEmail という名前の TextBox を追加し、双方向データ バインドを使用して、その Text プロパティを Email プロパティにバインドします。 EditItemTemplate に RequiredFieldValidator と RegularExpressionValidator を追加して、Email プロパティを編集しているビジターが有効なメール アドレスを入力したことを確認します。 "Comment" TemplateField の場合は、その EditItemTemplateComment という名前の複数行の TextBox を追加します。 TextBox の Columns および Rows プロパティをそれぞれ 40 と 4 に設定してから、双方向データ バインドを使用して、その Text プロパティを Comment プロパティにバインドします。

これらの TemplateField を構成すると、その宣言型マークアップは次のようになります。

<asp:TemplateField HeaderText="Email">    
     <ItemTemplate>    
          <asp:Label runat="server" ID="Label1" Text='<%# Eval("Email") %>'></asp:Label>    

     </ItemTemplate>    
     <EditItemTemplate>    
          <asp:TextBox runat="server" ID="Email" Text='<%# Bind("Email") %>'></asp:TextBox>    

          <asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server"    
               ControlToValidate="Email" Display="Dynamic"    
               ErrorMessage="You must provide an email address." 
               SetFocusOnError="True">*</asp:RequiredFieldValidator>    

          <asp:RegularExpressionValidator ID="RegularExpressionValidator1" runat="server"    
               ControlToValidate="Email" Display="Dynamic"    
               ErrorMessage="The email address you have entered is not valid. Please fix 
               this and try again."    
               SetFocusOnError="True"    

               ValidationExpression="\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*">*
          </asp:RegularExpressionValidator>    
     </EditItemTemplate>    
</asp:TemplateField>

<asp:TemplateField HeaderText="Comment">    
     <ItemTemplate>    
          <asp:Label runat="server" ID="Label2" Text='<%# Eval("Comment") %>'></asp:Label>    

     </ItemTemplate>    
     <EditItemTemplate>    
          <asp:TextBox runat="server" ID="Comment" TextMode="MultiLine"
               Columns="40" Rows="4" Text='<%# Bind("Comment") %>'>

          </asp:TextBox>    
     </EditItemTemplate>    
</asp:TemplateField>

ユーザー アカウントを編集または削除するときは、そのユーザーの UserName プロパティ値がわかっている必要があります。 この情報を GridView の DataKeys コレクションから取得できるように、GridView の DataKeyNames プロパティを "UserName" に設定します。

最後に、このページに ValidationSummary コントロールを追加し、その ShowMessageBox プロパティを True に、その ShowSummary プロパティを False に設定します。 これらの設定により、ユーザーがメール アドレスがないか、または無効な状態でユーザー アカウントを編集しようとすると、ValidationSummary にクライアント側のアラートが表示されます。

<asp:ValidationSummary ID="ValidationSummary1"
               runat="server"
               ShowMessageBox="True"
               ShowSummary="False" />

これで、このページの宣言型マークアップが完了しました。 次のタスクは、一連のユーザー アカウントを GridView にバインドすることです。 RoleBasedAuthorization.aspx ページの分離コード クラスに、Membership.GetAllUsers によって返された MembershipUserCollectionUserGrid GridView にバインドする BindUserGrid という名前のメソッドを追加します。 このメソッドは、最初のページ アクセス時に Page_Load イベント ハンドラーから呼び出します。

protected void Page_Load(object sender, EventArgs e)    
{    
     if (!Page.IsPostBack)    
          BindUserGrid();    
}

private void BindUserGrid()    
{    
     MembershipUserCollection allUsers = Membership.GetAllUsers();    
     UserGrid.DataSource = allUsers;    
     UserGrid.DataBind();    
}

このコードを有効にして、ブラウザー経由でこのページにアクセスします。 図 7 に示すように、システム内の各ユーザー アカウントに関する情報が一覧表示された GridView が表示されます。

The UserGrid GridView Lists Information About Each User in the System

図 7: システム内の各ユーザーに関する情報が一覧表示された UserGrid GridView (クリックするとフルサイズの画像が表示されます)

Note

UserGrid GridView には、すべてのユーザーがページングされていないインターフェイスで一覧表示されます。 この単純なグリッド インターフェイスは、ユーザーが数十人以上存在するシナリオには適していません。 1 つのオプションは、ページングを有効にするように GridView を構成することです。 Membership.GetAllUsers メソッドには、次の 2 つのオーバーロードがあります。入力パラメーターを受け付けず、すべてのユーザーを返すものと、ページ インデックスとページ サイズの整数値を受け取り、ユーザーの指定されたサブセットのみを返すものです。 2 つ目のオーバーロードでは、"すべての" ユーザー アカウントではなく、その正確なサブセットのみが返されるため、これによりユーザーをより効率的にページングできます。 数千のユーザー アカウントが存在する場合は、たとえば、選択された文字で始まる UserName を持つユーザーのみが表示されるフィルター ベースのインターフェイスを検討することもできます。 Membership.FindUsersByName method は、フィルターベースのユーザー インターフェイスを構築するために最適です。 このようなインターフェイスの構築については、今後のチュートリアルで説明します。

GridView コントロールでは、このコントロールが正しく構成されたデータ ソース コントロール (SqlDataSource や ObjectDataSource など) にバインドされている場合、組み込みの編集および削除サポートが提供されます。 ただし、UserGrid GridView では、そのデータがプログラムでバインドされているため、これらの 2 つのタスクを実行するコードを記述する必要があります。 特に、ビジターが GridView の [編集]、[キャンセル]、[更新]、または [削除] ボタンをクリックすると発生する GridView の RowEditingRowCancelingEditRowUpdatingRowDeleting イベントのイベント ハンドラーを作成する必要があります。

まず、GridView の RowEditingRowCancelingEditRowUpdating イベントのイベント ハンドラーを作成し、次のコードを追加します。

protected void UserGrid_RowEditing(object sender, GridViewEditEventArgs e)
{
     // Set the grid's EditIndex and rebind the data

     UserGrid.EditIndex = e.NewEditIndex;
     BindUserGrid();
}

protected void UserGrid_RowCancelingEdit(object sender, GridViewCancelEditEventArgs e)
{
     // Revert the grid's EditIndex to -1 and rebind the data
     UserGrid.EditIndex = -1;
     BindUserGrid();
}

protected void UserGrid_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
     // Exit if the page is not valid
     if (!Page.IsValid)
          return;

     // Determine the username of the user we are editing
     string UserName = UserGrid.DataKeys[e.RowIndex].Value.ToString();

     // Read in the entered information and update the user
     TextBox EmailTextBox = UserGrid.Rows[e.RowIndex].FindControl("Email") as TextBox;
     TextBox CommentTextBox = UserGrid.Rows[e.RowIndex].FindControl("Comment") as TextBox;

     // Return information about the user
     MembershipUser UserInfo = Membership.GetUser(UserName);

     // Update the User account information
     UserInfo.Email = EmailTextBox.Text.Trim();
     UserInfo.Comment = CommentTextBox.Text.Trim();

     Membership.UpdateUser(UserInfo);

     // Revert the grid's EditIndex to -1 and rebind the data
     UserGrid.EditIndex = -1;
     BindUserGrid();
}

RowEditing および RowCancelingEdit イベント ハンドラーは、単純に GridView の EditIndex プロパティを設定し、ユーザー アカウントの一覧をグリッドに再バインドします。 RowUpdating イベント ハンドラーでは、興味深いことが発生します。 このイベント ハンドラーは、まずデータが有効であることを確認してから、編集されたユーザー アカウントの UserName 値を DataKeys コレクションから取得します。 次に、2 つの TemplateField の EditItemTemplate 内の Email および Comment TextBox がプログラムで参照されます。 それらの Text プロパティには、編集されたメール アドレスとコメントが含まれています。

Membership API 経由でユーザー アカウントを更新するために、まずユーザーの情報を取得する必要があります。これは、Membership.GetUser(userName) を呼び出すことによって行います。 その後、返された MembershipUser オブジェクトの Email および Comment プロパティは、編集インターフェイスから 2 つの TextBox に入力された値で更新されます。 最後に、これらの変更が Membership.UpdateUser の呼び出しで保存されます。 RowUpdating イベント ハンドラーは、GridView をその編集前インターフェイスに戻すことによって完了します。

次に、RowDeleting イベント ハンドラーを作成してから、次のコードを追加します:

protected void UserGrid_RowDeleting(object sender, GridViewDeleteEventArgs e)
{
     // Determine the username of the user we are editing
     string UserName = UserGrid.DataKeys[e.RowIndex].Value.ToString();

     // Delete the user
     Membership.DeleteUser(UserName);

     // Revert the grid's EditIndex to -1 and rebind the data
     UserGrid.EditIndex = -1;
     BindUserGrid();
}

上記のイベント ハンドラーは、まず UserName 値を GridView の DataKeys コレクションから取得します。次に、この UserName 値が Membership クラスの DeleteUser メソッドに渡されます。 DeleteUser メソッドは、関連するメンバーシップ データ (このユーザーが属しているロールなど) を含むユーザー アカウントをシステムから削除します。 ユーザーを削除した後、グリッドの EditIndex が -1 に設定され (別の行が編集モードにある間にユーザーが [削除] をクリックした場合)、BindUserGrid メソッドが呼び出されます。

Note

[削除] ボタンでは、ユーザー アカウントを削除する前に、どのような種類の確認もユーザーに求められません。 アカウントが誤って削除される可能性を減らすために、何らかの形式のユーザー確認を追加することをお勧めします。 アクションを確認するための最も簡単な方法の 1 つは、クライアント側の確認ダイアログ ボックスを使用することです。 この手法の詳細については、「削除時のクライアント側での確認の追加」を参照してください。

このページが期待どおりに機能することを確認します。 任意のユーザーのメール アドレスやコメントを編集したり、任意のユーザー アカウントを削除したりできるはずです。 RoleBasedAuthorization.aspx ページはすべてのユーザーからアクセスできるため、どのユーザーでも (匿名ビジターでさえ) このページにアクセスしてユーザー アカウントを編集したり、削除したりできます。 このページを更新して、スーパーバイザーおよび管理者ロールのユーザーのみがユーザーのメール アドレスやコメントを編集でき、管理者のみがユーザー アカウントを削除できるようにしましょう。

「LoginView コントロールの使用」のセクションでは、LoginView コントロールの使用について説明し、ユーザーのロールに固有の手順を示します。 管理者ロールのユーザーがこのページにアクセスした場合は、ユーザーを編集および削除する方法に関する手順を示します。 スーパーバイザー ロールのユーザーがこのページに到達した場合は、ユーザーの編集に関する手順を示します。 また、ビジターが匿名であるか、あるいはスーパーバイザーまたは管理者ロールのどちらにも属していない場合は、ユーザー アカウント情報を編集したり削除したりできないことを説明するメッセージを表示します。 「プログラムによる機能の制限」のセクションでは、ユーザーのロールに基づいて、[編集] および [削除] ボタンの表示/非表示をプログラムで切り替えるコードを記述します。

LoginView コントロールの使用

以前のチュートリアルで見てきたように、LoginView コントロールは、認証されたユーザーと匿名ユーザーに異なるインターフェイスを表示するために役立ちますが、LoginView コントロールを使用すると、ユーザーのロールに基づいて異なるマークアップを表示することもできます。 LoginView コントロールを使用して、アクセスしているユーザーのロールに基づいて異なる手順を表示しましょう。

まず、UserGrid GridView の上に LoginView を追加します。 前に説明したように、LoginView コントロールには、AnonymousTemplateLoggedInTemplate という 2 つの組み込みテンプレートがあります。 これらのテンプレートの両方に、どのユーザー情報も編集したり削除したりできないことをユーザーに通知する簡単なメッセージを入力します。

<asp:LoginView ID="LoginView1" runat="server">
     <LoggedInTemplate>
          You are not a member of the Supervisors or Administrators roles. Therefore you
          cannot edit or delete any user information.
     </LoggedInTemplate>
     <AnonymousTemplate>
          You are not logged into the system. Therefore you cannot edit or delete any user

          information.
     </AnonymousTemplate>
</asp:LoginView>

AnonymousTemplateLoggedInTemplate に加えて、LoginView コントロールには、ロール固有のテンプレートである RoleGroup を含めることができます。 各 RoleGroup には、その RoleGroup が適用されるロールを指定する 1 つのプロパティ Roles が含まれています。 Roles プロパティは、1 つのロール ("Administrators" など)、またはロールのコンマ区切りリスト ("Administrators, Supervisors" など) に設定できます。

RoleGroup を管理するには、このコントロールのスマート タグから [RoleGroup の編集] リンクをクリックして、RoleGroup コレクション エディターを起動します。 2 つの新しい RoleGroup を追加します。 最初の RoleGroup の Roles プロパティを "Administrators" に、2 番目については "Supervisors" に設定します。

Manage the LoginView's Role-Specific Templates Through the RoleGroup Collection Editor

図 8: RoleGroup コレクション エディターを使用して LoginView のロール固有のテンプレートを管理する (クリックするとフルサイズの画像が表示されます)

[OK] をクリックして RoleGroup コレクション エディターを閉じます。これにより、LoginView の宣言型マークアップが更新され、RoleGroup コレクション エディターで定義された RoleGroup ごとの <asp:RoleGroup> 子要素を含む <RoleGroups> セクションが含まれます。 さらに、最初は AnonymousTemplateLoggedInTemplate だけが表示されていた LoginView のスマート タグ内の [ビュー] ドロップダウン リストに、追加された RoleGroup も含まれるようになりました。

RoleGroup を編集して、スーパーバイザー ロールのユーザーにはユーザー アカウントを編集する方法に関する手順が表示されるのに対して、管理者ロールのユーザーには編集および削除するための手順が表示されるようにします。 これらの変更を行うと、LoginView の宣言型マークアップは次のようになります。

<asp:LoginView ID="LoginView1" runat="server">
     <RoleGroups>
          <asp:RoleGroup Roles="Administrators">
               <ContentTemplate>
                    As an Administrator, you may edit and delete user accounts. 
                    Remember: With great power comes great responsibility!

               </ContentTemplate>
          </asp:RoleGroup>
          <asp:RoleGroup Roles="Supervisors">
               <ContentTemplate>
                    As a Supervisor, you may edit users&#39; Email and Comment information. 
                    Simply click the Edit button, make your changes, and then click Update.
               </ContentTemplate>
          </asp:RoleGroup>
     </RoleGroups>

     <LoggedInTemplate>
          You are not a member of the Supervisors or Administrators roles. 
          Therefore you cannot edit or delete any user information.
     </LoggedInTemplate>
     <AnonymousTemplate>
          You are not logged into the system. Therefore you cannot edit or delete any user
          information.
     </AnonymousTemplate>
</asp:LoginView>

これらの変更を行った後、このページを保存してから、ブラウザー経由でそこにアクセスします。 最初に、匿名ユーザーとしてこのページにアクセスします。 次のメッセージが表示されます。"システムにログインしてません。 そのため、ユーザー情報を編集または削除することはできません。"その後、認証されたユーザーではあるが、スーパーバイザーまたは管理者ロールのどちらにも属していないユーザーとしてログインします。 今度は、次のメッセージが表示されます。"スーパーバイザーまたは管理者ロールのメンバーではありません。 そのため、ユーザー情報を編集または削除することはできません。"

次に、スーパーバイザー ロールのメンバーであるユーザーとしてログインします。 今度は、スーパーバイザー ロール固有のメッセージが表示されます (図 9 を参照)。 また、管理者ロールのユーザーとしてログインした場合は、管理者ロール固有のメッセージが表示されます (図 10 を参照)。

Bruce is Shown the Supervisors Role-Specific Message

図 9: Bruce にはスーパーバイザー ロール固有のメッセージが表示される (クリックするとフルサイズの画像が表示されます)

Tito is Shown the Administrators Role-Specific Message

図 10: Tito には管理者ロール固有のメッセージが表示される (クリックするとフルサイズの画像が表示されます)

図 9 と図 10 のスクリーンショットが示すように、複数のテンプレートが適用される場合でも、LoginView は 1 つのテンプレートのみをレンダリングします。 Bruce と Tito はどちらもログインしているユーザーですが、LoginView は LoggedInTemplate ではなく、一致する RoleGroup のみをレンダリングします。 さらに、Tito は管理者ロールとスーパーバイザー ロールの両方に属していますが、LoginView コントロールはスーパーバイザー ロールではなく、管理者ロール固有のテンプレートをレンダリングします。

図 11 は、レンダリングするテンプレートを決定するために LoginView コントロールによって使用されるワークフローを示しています。 複数の RoleGroup が指定されている場合、LoginView テンプレートは、一致する "最初の" RoleGroup をレンダリングすることに注意してください。 つまり、スーパーバイザーの RoleGroup を最初の RoleGroup として、管理者の RoleGroup を 2 番目として配置している場合は、Tito がこのページにアクセスするとスーパーバイザーのメッセージが表示されます。

The LoginView Control's Workflow for Determining What Template to Render

図 11: レンダリングするテンプレートを決定するための LoginView コントロールのワークフロー (クリックするとフルサイズの画像が表示されます)

プログラムによる機能の制限

LoginView コントロールは、ページにアクセスしているユーザーのロールに基づいて異なる手順を表示しますが、[編集] および [キャンセル] ボタンはすべてのユーザーに表示されたままです。 匿名ビジターと、スーパーバイザーまたは管理者ロールのどちらにも属していないユーザーに対しては、[編集] および [削除] ボタンをプログラムで非表示にする必要があります。 [削除] ボタンは、管理者でないすべてのユーザーに対して非表示にする必要があります。 これを実現するために、CommandField の "Edit" および "Delete" LinkButton をプログラムで参照し、必要に応じてそれらの Visible プロパティを false に設定する少量のコードを記述します。

CommandField 内のコントロールをプログラムで参照するための最も簡単な方法は、最初にそれをテンプレートに変換することです。 これを実現するには、GridView のスマート タグから [列の編集] リンクをクリックし、現在のフィールドの一覧から CommandField を選択して [このフィールドを TemplateField に変換する] リンクをクリックします。 これにより、その CommandField が ItemTemplateEditItemTemplate を含む TemplateField に変換されます。 ItemTemplate には "Edit" および "Delete" LinkButton が含まれているのに対して、EditItemTemplate には "Update" および "Cancel" LinkButton が含まれています。

Convert the CommandField Into a TemplateField

図 12: CommandField を TemplateField に変換する (クリックするとフルサイズの画像が表示されます)

ItemTemplate で "Edit" および "Delete" LinkButton を更新して、それらの ID プロパティをそれぞれ EditButtonDeleteButton の値に設定します。

<asp:TemplateField ShowHeader="False">
     <EditItemTemplate>
          <asp:LinkButton ID="LinkButton1" runat="server" CausesValidation="True"
               CommandName="Update" Text="Update"></asp:LinkButton>

           <asp:LinkButton ID="LinkButton2" runat="server" CausesValidation="False"
                CommandName="Cancel" Text="Cancel"></asp:LinkButton>

     </EditItemTemplate>
     <ItemTemplate>
          <asp:LinkButton ID="EditButton" runat="server" CausesValidation="False"
               CommandName="Edit" Text="Edit"></asp:LinkButton>

           <asp:LinkButton ID="DeleteButton" runat="server" CausesValidation="False"
               CommandName="Delete" Text="Delete"></asp:LinkButton>

     </ItemTemplate>
</asp:TemplateField>

GridView にデータがバインドされるたびに、GridView はその DataSource プロパティ内にレコードを列挙し、対応する GridViewRow オブジェクトを生成します。 各 GridViewRow オブジェクトが作成されると、RowCreated イベントが発生します。 認可されていないユーザーに対して [編集] および [削除] ボタンを非表示にするには、このイベントのイベント ハンドラーを作成して、"Edit" および "Delete" LinkButton をプログラムで参照し、それに応じてそれらの Visible プロパティを設定する必要があります。

RowCreated イベントのイベント ハンドラーを作成し、次のコードを追加します。

protected void UserGrid_RowCreated(object sender, GridViewRowEventArgs e)
{
     if (e.Row.RowType == DataControlRowType.DataRow && e.Row.RowIndex != UserGrid.EditIndex)
     {
          // Programmatically reference the Edit and Delete LinkButtons
          LinkButton EditButton = e.Row.FindControl("EditButton") as LinkButton;

          LinkButton DeleteButton = e.Row.FindControl("DeleteButton") as LinkButton;

          EditButton.Visible = (User.IsInRole("Administrators") || User.IsInRole("Supervisors"));
          DeleteButton.Visible = User.IsInRole("Administrators");
     }
}

RowCreated イベントは、ヘッダー、フッター、ポケットベル インターフェイスなどを含む "すべての" GridView 行で発生することに注意してください。 "Edit" および "Delete" LinkButton をプログラムで参照するのは、編集モードではないデータ行を処理している場合だけにする必要があります (編集モードの行には [編集] と [削除] ではなく、[更新] と [キャンセル] のボタンがあるため)。 このチェックは、if ステートメントによって処理されます。

編集モードではないデータ行を処理している場合は、"Edit" および "Delete" LinkButton が参照され、それらの Visible プロパティは、User オブジェクトの IsInRole(roleName) メソッドによって返されたブール値に基づいて設定されます。 ユーザー オブジェクトは、RoleManagerModule によって作成されたプリンシパルを参照します。その結果として、IsInRole(roleName) メソッドが Roles API を使用して、現在のビジターが roleName に属しているかどうかを判定します。

Note

Roles クラスを直接使用して、User.IsInRole(roleName) の呼び出しを Roles.IsUserInRole(roleName) メソッドの呼び出しに置き換えることも可能でした。 この例では、Roles API を直接使用するより効率的であるため、プリンシパル オブジェクトの IsInRole(roleName) メソッドを使用することにしました。 このチュートリアルの前の方では、ユーザーのロールを Cookie にキャッシュするようにロール マネージャーを構成しました。 このキャッシュされた Cookie データは、プリンシパルの IsInRole(roleName) メソッドが呼び出された場合にのみ利用されます。Roles API を直接呼び出すと、常にロール ストアとの往復が必要になります。 ロールが Cookie にキャッシュされていない場合でも、プリンシパル オブジェクトの IsInRole(roleName) メソッドでは、要求中の初めて呼び出されたときに結果がキャッシュされるため、通常はこれを呼び出す方がより効率的です。 これに対して、Roles API ではキャッシュは実行されません。 RowCreated イベントは GridView 内のどの行でも 1 回発生するため、User.IsInRole(roleName) を使用するとロール ストアとの往復が 1 回だけ必要なのに対して、Roles.IsUserInRole(roleName) では N 回の往復が必要です。ここで、N は、グリッドに表示されているユーザー アカウントの数です。

[編集] ボタンの Visible プロパティは、このページにアクセスしているユーザーが管理者またはスーパーバイザー ロールに属している場合は true に設定され、そうでない場合は false に設定されます。 [削除] ボタンの Visible プロパティは、ユーザーが管理者ロールに属している場合にのみ true に設定されます。

ブラウザー経由でこのページをテストします。 匿名ビジターとして、あるいはスーパーバイザーまたは管理者のどちらでもないユーザーとしてこのページにアクセスした場合、CommandField は空です。引き続き存在しますが、[編集] または [削除] ボタンのない薄いスライバーとしてだけです。

Note

スーパーバイザーでも管理者でもないユーザーがこのページにアクセスしているときに CommandField を完全に非表示にすることができます。 これは、読者のための演習として残しておきます。

The Edit and Delete Buttons are Hidden for Non-Supervisors and Non-Administrators

図 13: スーパーバイザーでも管理者でもないユーザーに対して [編集] および [削除] ボタンが非表示になっている (クリックするとフルサイズの画像が表示されます)

スーパーバイザー ロールに属している (ただし、管理者ロールには属していない) ユーザーがアクセスした場合は、[編集] ボタンだけが表示されます。

While the Edit Button is Available for Supervisors, the Delete Button is Hidden

図 14: スーパーバイザーは [編集] ボタンを使用できるが、[削除] ボタンが非表示になっている (クリックするとフルサイズの画像が表示されます)

また、管理者がアクセスした場合は、[編集] ボタンと [削除] ボタンの両方にアクセスできます。

The Edit and Delete Buttons are Available Only for Administrators

図 15: [編集] および [削除] ボタンは管理者のみが使用できる (クリックするとフルサイズの画像が表示されます)

手順 3: ロール ベースの認可規則のクラスとメソッドへの適用

手順 2 では、編集機能をスーパーバイザーおよび管理者ロールのユーザーに、削除機能を管理者のみに制限しました。 これは、認可されていないユーザーに関連付けられたユーザー インターフェイス要素をプログラムによる方法で非表示にすることによって実現されました。 このような方法では、認可されていないユーザーが特権アクションを実行できなくなることは保証されません。 後で追加されるか、または認可されていないユーザーに対して非表示にし忘れたユーザー インターフェイス要素が存在する可能性があります。 あるいは、ハッカーが、ASP.NET ページに目的のメソッドを実行させるための他の何らかの方法を発見する可能性があります。

認可されていないユーザーが特定の機能に絶対にアクセスできないようにするための簡単な方法は、そのクラスまたはメソッドを PrincipalPermission 属性で修飾することです。 .NET ランタイムはクラスを使用したり、そのメソッドのうちの 1 つを実行したりする場合、現在のセキュリティ コンテキストにアクセス許可があることをチェックして確認します。 PrincipalPermission 属性は、これらの規則を定義できるメカニズムを提供します。

PrincipalPermission 属性の使用については、以前の「ユーザー ベースの認可」のチュートリアルで説明しました。 具体的には、GridView の SelectedIndexChanged および RowDeleting イベント ハンドラーを修飾して、それらをそれぞれ、認証されたユーザーと Tito だけが実行できるようにする方法について確認しました。 PrincipalPermission 属性はロールとも連携します。

GridView の RowUpdating および RowDeleting イベント ハンドラーで PrincipalPermission 属性を使用して、認可されていないユーザーの実行を禁止する方法を示しましょう。 そのために必要なのは、各関数定義の上に適切な属性を追加することだけです。

[PrincipalPermission(SecurityAction.Demand, Role = "Administrators")]
[PrincipalPermission(SecurityAction.Demand, Role = "Supervisors")]
protected void UserGrid_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
     ...
}

[PrincipalPermission(SecurityAction.Demand, Role = "Administrators")]
protected void UserGrid_RowDeleting(object sender, GridViewDeleteEventArgs e)
{
     ...
}

RowUpdating イベント ハンドラーの属性が、このイベント ハンドラーは管理者またはスーパーバイザー ロールのユーザーだけが実行できることを指定するのに対して、RowDeleting イベント ハンドラーの上にある属性はその実行を管理者ロールのユーザーに制限します。

Note

PrincipalPermission 属性は、System.Security.Permissions 名前空間内のクラスとして表されます。 この名前空間をインポートするには、分離コード クラス ファイルの一番上に必ず using System.Security.Permissions ステートメントを追加してください。

何らかの方法で管理者以外のユーザーが RowDeleting イベント ハンドラーを実行しようとするか、またはスーパーバイザーでも管理者でもないユーザーが RowUpdating イベント ハンドラーを実行しようとすると、.NET ランタイムによって SecurityException が生成されます。

If the Security Context is not Authorized to Execute the Method, a SecurityException is Thrown

図 16: セキュリティ コンテキストがメソッドの実行を認可されていない場合は、SecurityException がスローされる (クリックするとフルサイズの画像が表示されます)

ASP.NET ページに加えて、多くのアプリケーションには、さまざまなレイヤー (ビジネス ロジック レイヤーやデータ アクセス レイヤーなど) を含むアーキテクチャもあります。 これらのレイヤーは通常、クラス ライブラリとして実装され、ビジネス ロジックやデータ関連の機能を実行するためのクラスとメソッドを提供します。 PrincipalPermission 属性は、これらのレイヤーにも認可規則を適用するために役立ちます。

PrincipalPermission 属性を使用してクラスやメソッドで認可規則を定義する方法の詳細については、Scott GuthriePrincipalPermissionAttributes を使用したビジネスおよびデータ レイヤーへの認可規則の追加に関するブログ エントリを参照してください。

まとめ

このチュートリアルでは、ユーザーのロールに基づいて、粗い認可規則ときめ細かい認可規則を指定する方法について説明しました。 ASP.NET の URL 認可機能を使用すると、ページ開発者は、どの ID がどのページへのアクセスを許可または拒否されるかを指定できます。 以前の「ユーザー ベースの認可」のチュートリアルで説明したように、URL 認可規則はユーザーごとに適用できます。 また、このチュートリアルの手順 1 で説明したように、ロールごとに適用することもできます。

きめ細かい認可規則は、宣言的にまたはプログラムで適用できます。 手順 2 では、LoginView コントロールの RoleGroup 機能を使用して、アクセスしているユーザーのロールに基づいて異なる出力をレンダリングする方法について説明しました。 また、ユーザーが特定のロールに属しているかどうかをプログラムで判定し、それに応じてページの機能を調整する方法についても説明しました。

プログラミングに満足!

もっと読む

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

作成者について

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

特別な感謝

このチュートリアル シリーズは、多くの役に立つ校閲者によってレビューされました。 このチュートリアルのリード レビュー担当者には、Suchi Banerjee と Teresa Murphy が含まれます。 今後の MSDN の記事を確認することに関心がありますか? ご希望の場合は、mitchell@4GuysFromRolla.com 宛にメールをお送りください