管理エリアがあり、管理者だけがそのエリアに入るようにしたいです。Admin 領域のすべてのコントローラーに Authorized 属性を追加することを検討しました。エレガントなソリューションはありませんか、それともこの機能はフレームワーク自体にありませんか?
編集:申し訳ありませんが、これについては前に言及する必要がありました。AuthorizeAttribute から派生したカスタム AuthorizedAttribute を使用しています。
管理エリアがあり、管理者だけがそのエリアに入るようにしたいです。Admin 領域のすべてのコントローラーに Authorized 属性を追加することを検討しました。エレガントなソリューションはありませんか、それともこの機能はフレームワーク自体にありませんか?
編集:申し訳ありませんが、これについては前に言及する必要がありました。AuthorizeAttribute から派生したカスタム AuthorizedAttribute を使用しています。
Web.config ベースのセキュリティは、MVC アプリケーションではほとんど使用しないでください。この理由は、複数の URL がコントローラーにヒットする可能性があり、これらのチェックを Web.config に入れると必ず何かが見落とされるためです。注意 - コントローラはエリアに関連付けられていませんが、ルートはエリアに関連付けられています。MVC コントローラー ファクトリは、競合がなければ、領域以外の要求に対して Areas/ フォルダーからコントローラーを喜んで提供します。
たとえば、デフォルトのプロジェクト構造を使用して、AdminDefaultController で管理領域を追加すると、/Admin/AdminDefault/Indexおよび/AdminDefault/Index を介してこのコントローラーをヒットできます。
サポートされている唯一の解決策は、コントローラーの基本クラスに属性を配置し、領域内の各コントローラーがその基本クラスのサブクラスになるようにすることです。
私はちょうどこの同じ問題を調査しています。エリアに基づいてコントローラーを保護することはできないため、より単純なオプションが思い浮かびます。
Controller をオーバーライドする各領域のベース コントローラー定義を作成し、これに必要なセキュリティを追加します。次に、領域内の各コントローラーが Controller ではなく AreaController をオーバーライドするようにする必要があります。例えば:
/// <summary>
/// Base controller for all Admin area
/// </summary>
[Authorize(Roles = "Admin")]
public abstract class AdminController : Controller { }
このベースから管理領域の各コントローラーを派生させる必要があります。
public class HomeController : AdminController
{
// .. actions
}
ただし、少なくとも、エリアのセキュリティを定義する単一のポイントがあります。
私はこれを始めたばかりです...しかし、これまでのところ、これは私にとってかなりうまくいっています。
カスタム AuthorizeAttribute クラスを作成し、これを RegisterGlobalFilters 関数に追加します。
CustomAuthorizeAttribute では、領域に基づいてさまざまな条件をチェックします。
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new CustomAuthorizeAttribute());
filters.Add(new HandleErrorAttribute());
}
}
public class CustomAuthorizeAttribute : AuthorizeAttribute
{
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
var routeData = httpContext.Request.RequestContext.RouteData;
var controller = routeData.GetRequiredString("controller");
var action = routeData.GetRequiredString("action");
var area = routeData.DataTokens["area"];
var user = httpContext.User;
if (area != null && area.ToString() == "Customer")
{
if (!user.Identity.IsAuthenticated)
return false;
}
else if (area != null && area.ToString() == "Admin")
{
if (!user.Identity.IsAuthenticated)
return false;
if (!user.IsInRole("Admin"))
return false;
}
return true;
}
}
すべての管理コードが 1 つのコントローラーにある場合は、Authorize をクラス全体に追加します。
[Authorize]
public class AdminController : Controller
{
.......
}
.. 非常に大雑把ですが、このようなものが欲しいと思いますか?
[Authorize(Roles = "Admins")]
public ActionResult Register()
{
ViewData["roleName"] = new SelectList(Roles.GetAllRoles(), "roleName");
ViewData["PasswordLength"] = MembershipService.MinPasswordLength;
return View();
}