ASP.NET MVCを使用すると、ユーザーは、設計時のように機能(つまりアクション)にアクセス許可を割り当てることができます。
[Authorize(Roles = "Administrator,ContentEditor")]
public ActionResult Foo()
{
return View();
}
実際に権限を確認するには、(Razor)ビューで次のステートメントを使用します。
@if (User.IsInRole("ContentEditor"))
{
<div>This will be visible only to users in the ContentEditor role.</div>
}
このアプローチの問題は、すべての権限を設定し、設計時に属性として割り当てる必要があることです。 (属性はDLLでコンパイルされるため、現在、[Authorize(Roles = "Administrator、ContentEditor")]などの属性を(追加のアクセス許可を許可するために)適用するメカニズムがないことを認識しています。 ランタイム。
このユースケースでは、クライアントは、どのユーザーがどの権限を持っているかを変更できる必要があります展開後。
たとえば、クライアントは、ContentEditor
ロールのユーザーが特定のタイプのコンテンツを編集できるようにしたい場合があります。おそらく、ユーザーはルックアップテーブルの値を編集することを許可されていませんでしたが、クライアントはユーザーに許可せずにこれを許可したいと考えていますall次に高い役割のアクセス許可。代わりに、クライアントは単にmodifyユーザーのcurrentロールで使用可能なアクセス許可を求めています。
MVCコントローラー/ビュー/アクションのアクセス許可を(データベースのように)属性の外部で定義し、実行時に評価および適用できるようにするために使用できる戦略は何ですか?
可能であれば、ASP.NETメンバーシップおよびロールプロバイダーの機能にできる限り近づき、ASP.NETが提供する他の利点を引き続き活用できるようにしたいと考えています。
アイデアや洞察を事前に感謝します。
MVCコントローラー/ビュー/アクションのアクセス許可を(データベースのように)属性の外部で定義し、実行時に評価および適用できるようにするために使用できる戦略は何ですか?
カスタムのAuthorize属性は、これを実現する1つの可能性です。
public class MyAuthorizeAttribute : AuthorizeAttribute
{
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
Roles = ... go ahead and fetch those roles dynamically from wherever they are stored
return base.AuthorizeCore(httpContext);
}
}
その後:
[MyAuthorize]
public ActionResult Foo()
{
return View();
}
私は怠惰なので、自分の属性をローリングすることを気にすることはできず、これに FluentSecurity を使用しました。実行時にルールを適用する機能に加えて、ロールメンバーシップをチェックするカスタムの方法が可能になります。私の場合、各役割の構成ファイル設定があり、次のようなものを実装します。
// Map application roles to configuration settings
private static readonly Dictionary<ApplicationRole, string>
RoleToConfigurationMapper = new Dictionary<ApplicationRole, string>
{
{ ApplicationRole.ExceptionLogViewer, "ExceptionLogViewerGroups" }
};
次に、アプリケーションの役割が次のように適用されます。
SecurityConfigurator.Configure(
configuration =>
{
configuration.GetAuthenticationStatusFrom(() =>
HttpContext.Current.User.Identity.IsAuthenticated);
configuration.GetRolesFrom(() =>
GetApplicationRolesForPrincipal(HttpContext.Current.User));
configuration.ForAllControllers().DenyAnonymousAccess();
configuration.For<Areas.Administration.Controllers.LogViewerController>()
.RequireRole(ApplicationRole.ExceptionLogViewer);
});
filters.Add(new HandleSecurityAttribute());
その後、チェックはによって実行されます
public static object[] GetApplicationRolesForPrincipal(IPrincipal principal)
{
if (principal == null)
{
return new object[0];
}
List<object> roles = new List<object>();
foreach (KeyValuePair<ApplicationRole, string> configurationMap in
RoleToConfigurationMapper)
{
string mappedRoles = (string)Properties.Settings.Default[configurationMap.Value];
if (string.IsNullOrEmpty(mappedRoles))
{
continue;
}
string[] individualRoles = mappedRoles.Split(',');
foreach (string indvidualRole in individualRoles)
{
if (!roles.Contains(configurationMap.Key) && principal.IsInRole(indvidualRole))
{
roles.Add(configurationMap.Key);
if (!roles.Contains(ApplicationRole.AnyAdministrationFunction))
{
roles.Add(ApplicationRole.AnyAdministrationFunction);
}
}
}
}
return roles.ToArray();
}
もちろん、データベースからロールをプルすることもできます。これの良いところは、開発中にさまざまなルールを適用できることです。さらに、誰かがすでに私のために大変な作業を行っています。
また、タスク/アクティビティベースのセキュリティを実行し、それらのタスクを実行するためのアクセス許可をさまざまなグループに動的に割り当てることも検討できます。
これを処理するには、プロバイダーを少しマングルする必要がありますが、.net認証とインラインを維持することは可能です。
http://www.lhotka.net/weblog/PermissionbasedAuthorizationVsRolebasedAuthorization.aspx
メソッドまたはコントローラーベースの承認を行う必要がある場合(メソッドまたはコントローラー全体へのアクセスを拒否する)、コントローラーベースでOnAuthorizationをオーバーライドして、独自の承認を行うことができます。次に、テーブルを作成して、そのコントローラー/メソッドに割り当てられているアクセス許可を検索し、そこから移動できます。
非常によく似たカスタムグローバルフィルターを実行することもできます。
2番目のアプローチを使用する別のオプションは、次のように言うことです。
@if (User.IsInRole(Model.MethodRoles))
{
<div>This will be visible only to users in the ContentEditor role.</div>
}
次に、コントローラーで、そのメソッドに割り当てられたロールをMethodRolesに入力します。