私は一種のオンライン ワークプレイスである Web サイトを開発しています。何人かのユーザーと進行中のコンピューター プログラミング プロジェクトがあり、各ユーザーは複数の役割を持つことができます。たとえば、特定の 1 人のユーザーがプロジェクトのプロジェクト マネージャーと開発者になることができます。別のプロジェクトのために。当然のことながら、プロジェクト マネージャーは、プロジェクトの開発者よりも権限が大きくなります。私の質問は、コードでこれをきちんと管理する方法ですか? カスタム ロール プロバイダーを使用し、これで Authorize 属性を使用するつもりでしたが、特定のプロジェクトでユーザーのロールを見つけるには、プロジェクト ID とユーザー ID が必要になるため、それだけでは十分ではありません。
7 に答える
最初に、拡張ロール管理用の追加テーブルを作成する必要があります。たとえば、 のコンテキストでprojects
との関係があります。users
operations
controller's actions
1 つの方法は、独自のテーブルを作成することですroles
。その場合、 Asp net のみを使用しますmembership users
が、それはすべて要件によって異なります。
次に、で処理する必要がありますMVC
。私の意見では、独自のカスタムAuthorization
属性を使用して実装し、コントローラーのアクションを属性の代わりにカスタム承認属性で装飾するのが最善の方法[Authorization]
です。
とてもシンプルです。
[CustomAuthorize]
//[Authorize]
public ActionResult GetProjectTasks(string projectname)
{
}
そのためには、クラスを継承する必要があり、インターフェイスFilterAttribute
も実装する必要がありIAuthorizationFilter
ます。
public void OnAuthorization(AuthorizationContext filterContext)
{
HttpCookie authCookie = filterContext.HttpContext.Request.Cookies[FormsAuthentication.FormsCookieName];
if (authCookie != null)
{
FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);
var identity = new GenericIdentity(authTicket.Name, "Forms");
var principal = new GenericPrincipal(identity, new string[] { authTicket.UserData });
filterContext.HttpContext.User = principal;
}
var controller = filterContext.ActionDescriptor.ControllerDescriptor.ControllerName;
var action = filterContext.ActionDescriptor.ActionName;
var user = filterContext.HttpContext.User;
var ip = filterContext.HttpContext.Request.UserHostAddress;
var isAccessAllowed = CustomAuthenticationLogic.IsAccessAllowed(controller, action, user, ip);
if (!isAccessAllowed)
{
// Code if user is authenticated
FormsAuthentication.RedirectToLoginPage();
}
}
メソッドでは、名前、名前OnAuthorization
などのカスタム認証ロジックで必要になる可能性のあるすべての情報を取得できます。このメソッドからカスタム認証ロジックを呼び出すだけです。カスタム認証ロジックは次のようになります。HttpContext
Controller
Action
public class CustomAuthenticationLogic
{
public static bool IsAccessAllowed(string controller, string action, IPrincipal user, string ip)
{
//
// Your custom logic here
//
}
}
少し前にいくつかの調査を行ったので、次のことを保証できます。
- ASP.NET の組み込み機能はおそらく役に立たないでしょう (プロジェクト ID などを考慮する方法はありません)。
- 役割ベースのアクセス モデルが最も適していますが、それを実装するにはさまざまな方法があります。Rusted が提案する AzMan は実際には優れていますが、コンテキスト関連のルールを管理するのは難しい場合があります。例: ユーザー A がプロジェクト C で操作 B を実行しているときに、日曜日としましょう。アズマンを見てください。
- アクセス ルールとコードを混在させることは、非常に悪いことです。セキュリティ モデルは、アプリケーションの動作方法 (ASP.NET MVC) に関連付ける必要はないため、これは間違っています。
var isAllowed = AccessControl.IsAccessAllowed(controller, action, user, ip);
次のようになります。
var isAllowed = AccessControl.IsAccessAllowed(user, operation, context);
その後、いつでも好きなときに使用できます。各アクションで、または属性としてラップします。
ここで、操作は「ログイン」、「返信の投稿」、「トピックの読み取り」などです。コンテキストは、「プロジェクト ID」、「曜日」、「ユーザー IP」などのように、それ以外のすべてです。
ロールの重複、コンテキストなど、多くのことを記述することができます。要するに、「.NET ロール ベースのアクセス モデル」に対する Google は、小さなカスタム セキュリティ フレームワークを記述する方が簡単かもしれません。ユーザー、ロール、オペレーション、プロジェクト ID で機能させる
操作はロールに割り当てられ、ロールは定義されたプロジェクト ID を持つユーザーに割り当てられます。操作とロールをハードコーディングできるため、DB では小さな変更が 1 つだけになります: ユーザーからロールへのマッピング
AzManの主なアイデアは、操作に対するプログラミングの概念です。
操作は、使用法が重複してはならず、開発者によってのみ定義されるべき非常に細かいものです。操作をタスクにグループ化し、タスクをロールにグループ化してから、プリンシパル (ユーザーとグループ) をロールにマッピングすることで、アプリで承認を定義するための非常に強力なモデルが得られます。操作を直接プログラミングするため、ユーザーが持つ役割をコードで知る必要はなく、実行時に管理者が変更できます。実際、コードで使用する操作を使用するために、まったく異なる一連のロールを誰かが定義することができ、コードをまったく変更する必要はありません。本当の力はそこにある。
「アプリで AzMan を使用する」という意味ではありません (ただし、試してみてください)。これは強力なモデルですが、複雑でもあり、単純なものにはおそらくやり過ぎです。役割が 1 つまたは 2 つしかなく、それらが保護する操作が重複していないか、変更される可能性が低い場合は、おそらく保証されていません。
より複雑なルールがあり、属性が十分でない場合は、ユーザーが一部の機能にアクセスできるかどうかをコントローラーで計算し、それらの機能へのアクセスを反映するかどうかを反映する ViewModel のプロパティを追加できます。
このようにして、ビューは非常にスリムになり、それらの ViewModel ブール値プロパティに応じて表示されます。
したがって、ユーザーが読み取りしかできないと想像すると、承認規則に応じてコントローラに入力されるプロパティ bool IsReadOnly を持つことができます。これは、たとえば、テキスト ボックスの代わりにラベルを生成するためにビューで使用されます。
groups
に基づいて作成できますroles
。
次に、別のユーザーを特定のグループに追加します。グループは >
1) Admin Group
2) Developer Group
3) Project1-QA Group
4) Project2-Manager Group
データベースの設計に応じて、[user - group]
とのマッピングを保存します。[group - projects]
1 人のユーザーに対して必要な数の役割 (グループ) を持つことができます。
インターフェイスを実装する代わりにAuthorize
、組み込みフィルターを拡張してカスタム フィルターを作成することをお勧めします。ビルトインは、キャッシュの問題やその他の問題を処理する多くの配管作業を行います。インターフェイスを実装する場合は、それらすべての作業を行う必要があります。AuthorizeAttribute
IAuthorizationFilter
AuthorizeAttribute
メソッドをオーバーライドするAuthorizeCore
必要があり、そこでロール チェック ロジックをすべて実行します。user id
セッションに保存する必要project id
があり、それを把握する必要があります。
public override bool AuthorizeCore(HttpContextBase httpContext)
{
}
AuthorizeAttribute ソース コード - http://aspnetwebstack.codeplex.com/SourceControl/changeset/view/913d37658a44#src%2fSystem.Web.Mvc%2fAuthorizeAttribute.cs
カスタム承認属性の例: http://msdn.microsoft.com/en-us/library/ee707357(v=vs.91).aspx
非常に単純なアプローチ-サイト全体のアクセス制御の場合、INT列をユーザーテーブルに追加し、そのINTの各ビットを[flags]
列挙型にマップできます-たとえば[Flags] enum Access { UpdateProjects, AddProjects }
.
プロジェクトごとのアクセス制御の場合、ProjectID (Project テーブルへの外部キー)、UserID (User テーブルへの外部キー)、Role (INT) の 3 つの列を持つ、たとえば ProjectAccessControl という名前のテーブルを作成します。Role 列は INT であり、その各ビットは異なるブール値フラグを意味する必要があり (前の例のように、これを C# の列挙型にマップできます)、最初のビットがオンの場合、ユーザーは説明を更新する権利を持っていると言えます。 2 番目のビットがオンの場合、ユーザーはスケジュールなどを変更できます。
[Flags]
enum ProjectAccessRole
{
UpdateDescription,
ChangeSchedule,
etc...
}
コードでは、ユーザーの役割がスケジュールを更新する権利を持っているかどうかを次の方法でテストできます。
if( (intUserRole & ProjectAccessRole.ChangeSchedule)
== ProjectAccessRole.ChangeSchedule)
{
/*user has right*/
}
次に、このチェックを 2 つのパラメーターを取る単純な関数にラップできます。次に、 を呼び出すだけHasRights(intUserRole, ProjectAccessRole.ChangeSchedule);
です。