の拡張とは別に、 を拡張MembershipProvider
することもできますRoleProvider
。RoleProvider は、ユーザーが属するグループの確認、新しいロールの登録、ロールへのユーザーの追加などを担当します。ロールを操作するには、多くの静的メソッドを含む Roles クラスを使用します。
これに加えて、コントローラーをヒットするたびに、HttpContext.User
を実装するプロパティを照会できますIPrincipal
。このプロパティにはIsInRole
、RoleProvider と通信してユーザーが特定のグループに属しているかどうかの情報を取得するために使用されるメソッドがあります。
また、コントローラまたはアクションへのアクセスを許可するために、Authorization
属性を使用して、コントローラにアクセスできる特定のロールを一覧表示できます。
ロールは (キャッシュするために) Cookie に格納するか、 global.asaxApplication_AuthenticateRequest
に実装して手動で初期化することができます。このオブジェクトは HttpContext.User に渡されます。このオブジェクトのコンストラクターは、IsInRole メソッドで照会されるロールの配列を受け入れます。GenericPrincipal
protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
// Check if user is authenticated
if (HttpContext.User != null)
{
// Extract roles from a cookie if you used FormsAuthentication
// or read them from a cookie or from some other cached location
// Split roles into array of strings
var roles = listOfRoles.ToArray(); // If it is stored in a List<string>.
var identity = HttpContext.User.Identity;
var principal = new GenericPrincipal(identity, roles);
HttpContext.User = principal;
}
}
上記のコードはテストされていません。思いつきで書きました。ロールをキャッシュする方法と、それらを最も効率的な方法で使用する方法がかなりよくわかるはずです。
更新:各ロールが「検索を使用する」、「何かを行うことができる」、「それを行うことができる」などの1つ以上の機能を持つことができる、より高度なオプションが必要な場合は、次のセキュリティロジックを実装します:
- ユーザー
- 役割 (ユーザーは役割に属します)
- AccessRight (ロールは 1 つ以上のアクセス権を持つことができます)。
UsersRoles テーブルは、ユーザーを特定のロールに追加するためのものです。RolesAccessRights テーブルは、各ロールに特定の権限を定義する場所です。ユーザーが機能と話すことはありません。(ところで、この命名規則は単なる例です。命名規則に従います)。
私の最後の仕事では、これが監査システムをどのように実装したかです (それは Web フォームベースでした)。ただし、MVC では、オーバーライドAuthorizationAttribute
してユーザーの役割を確認し、役割にアクセス権が定義されているかどうかを確認できます。特定のセキュリティ要件があることを考慮すると、必要性と必要性が見られるすべてのアクションでこの属性を使用する必要があります。
このロジックを実装する予定がある場合は、Membership、MembershipUser、および Roles について忘れてください。正直なところ、私はこれらのクラスをもう使用していません。私は独自のカスタム セキュリティを実装しており、更新や変更を必要とせずに最後の 4 つのプロジェクトで使用しました。
更新 2 : 私たちが使用したセキュリティ ソリューションは、カスタムの MembershipProvider と RoleProvider に基づいていました。今考えれば、AccessLevel テーブルへのアクセスは Entity Framework 経由でマッピングする必要があるため、それに依存するのは間違いでした。したがって、セキュリティ テーブルをクエリする方法が必要でした。
あなたへの私の提案は、メンバーシップおよびロール関連のクラスを完全に無視することです。1 つ目の理由は、プロバイダーをオーバーライドするときに不要なメソッドやプロパティに煩わされるのを避けるためです。throw new NotSupportedException()
メソッド本体に を含むメソッドが多すぎます。
推奨される実装
次のテーブルが必要になります。
- ユーザー- (UserId、UserName、Password の 3 つの列が少なくとも必要です)。パスワードをハッシュしたい場合は、salt も保存する必要があるかもしれません。FirstName、LastName などの他の列。別のテーブルに保存し、それを UserId にリンクすることをお勧めします。
int
UserId タイプについては、またはを使用するかどうかはあなた次第ですGuid
。
- 役割- (少なくとも 2 つの列 RoleId、RoleName が必要です)。繰り返しますが、UserId と同様に、どのデータ型を使用するかはユーザー次第です。
- UsersRoles - UserId と RoleId を格納します。ロールがIsActiveであるかどうかなどのプロパティをビット値で格納したい場合があります。
- AccessRights - アクセス権のキーを格納する場所です。あなたの場合は、UseSearch、EditPosts、DeletePostsなどです。ここでは、少なくとも 3 つの列 AccessRightId、AccessRightKey および AccessRightDescription を使用する必要があります。この説明フィールドは、アクセス権キーがたくさんある場合に非常に役立ちます。
- RolesAccessRights - これは、特定のアクセス権を追加したロールを定義する場所です。ロールへの特定のアクセス権を無効にするために、IsActiveビット値も用意します。
MVC では、AuthorizationAttributeをオーバーライドします。この属性では、コントローラーやアクションにアクセスできるアクセス権のリストを指定します。これをどのように行うかは完全にあなた次第ですが、AccessRightsKeys と同じ値のリストを持つ列挙型を作成します。そうすれば、文字列ベースのリストの代わりに、厳密に型指定されたアクセス権を使用できます。カスタム承認属性の実装の詳細については、参照リストを参照してください。
この属性内で、ユーザー ID を読み取り、ロールを取得します。指定した AccessRightsKeys をロール (RolesAccessRights テーブル) と比較して、ロールにアクセス権があるかどうか、およびルールがアクティブかどうかを確認します。
ソリューション ベースの実装に関しては、セキュリティ ベースのリポジトリおよび作業単位ソリューションと通信するセキュリティ サービス レイヤーを実装します。MySQL を使用しているため、どの ORM を使用できるのか、または MySQL 用の OLEDB プロバイダーを備えた ADO.NET に依存する必要があるのか わかりません。
私の通常のアプローチはトップダウンのアプローチです。上位層 (プレゼンテーション層など) から実装し、データ アクセス層に向かって下ります。そうすれば、最後に私が実際に使用する方法しかなく、冗長性はありません。
さて、これでこれがどのように行われるかについてのイメージが得られることを願っています。所要時間については、約8〜10時間でこれを行うことができます.
参照:
- ロール プロバイダーの実装
- 役割クラス
- 方法: カスタム AuthorizationAttribute を作成する