当前接受的答案并不是最安全的解决方案,因为它要求开发人员始终记住为任何新的控制器或操作(“黑名单”;允许用户访问所有内容)继承该新基类除非手动限制操作)。当不熟悉您的习惯的新开发人员被引入项目时,这尤其会导致问题。如果这样做,很容易忘记继承正确的控制器类,尤其是在您将注意力从项目上移开数周、数月或数年之后。如果开发者忘记继承,则说明项目存在安全漏洞并不明显。
对此问题的更安全的解决方案是拒绝访问所有请求,然后用允许访问操作的角色装饰每个操作(“白名单”;阻止所有用户访问,除非手动允许)。现在,如果开发人员忘记将适当的授权列入白名单,用户会通知您,这就像查看其他控制器以提醒有关如何提供适当的访问权限一样简单。但是,至少没有重大的安全漏洞。
在 App_Start/FilterConfig.cs 文件中,修改 FilterConfig 类:
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
...
//Deny access to all controllers and actions so that only logged in Administrators can access them by default
filters.Add(new System.Web.Mvc.AuthorizeAttribute() { Roles = "Administrator" });
}
这使得所有操作都无法访问,除非用户以管理员身份登录。然后,对于您希望不同授权用户访问的每个操作,您只需使用[OverrideAuthorization] 和[Authorize] 进行装饰。
在您的业务逻辑中,这允许您以多种方式使用 Authorize 属性,而无需担心未经授权的用户访问任何功能。下面是一些例子。
示例 1 - 仅允许登录的管理员和调度程序用户访问 Index() Get 和 Post 方法。
public class MarkupCalculatorController : Controller //Just continue using the default Controller class.
{
// GET: MarkupCalculator
[OverrideAuthorization]
[Authorize(Roles = "Administrator,Dispatcher")]
public ActionResult Index()
{
//Business logic here.
return View(...);
}
// POST: DeliveryFeeCalculator
[HttpPost]
[ValidateAntiForgeryToken]
[OverrideAuthorization]
[Authorize(Roles = "Administrator,Dispatcher")]
public ActionResult Index([Bind(Include = "Price,MarkedupPrice")] MarkupCalculatorVM markupCalculatorVM)
{
//Business logic here.
return View(...);
}
}
示例 2 - 只有经过身份验证的用户才能访问 Home 控制器的 Index() 方法。
public class HomeController : Controller
{
[OverrideAuthorization]
[Authorize] //Allow all authorized (logged in) users to use this action
public ActionResult Index()
{
return View();
}
}
示例 3 - 可以使用 [AllowAnonymous] 属性允许未经身份验证的用户(即匿名用户)访问方法。这也会自动覆盖全局过滤器,而不需要 [OverrideAuthorization] 属性。
// GET: /Account/Login
[AllowAnonymous]
public ActionResult Login(string returnUrl)
{
ViewBag.ReturnUrl = returnUrl;
return View();
}
//
// POST: /Account/Login
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
...
}
示例 4 - 仅允许管理员访问缺少 [Authorize] 属性的方法。
public class LocationsController : Controller
{
// GET: Locations
public ActionResult Index()
{
//Business logic here.
return View(...);
}
}
一些注释。
如果要将对特定操作的访问限制为特定角色,则必须使用 [OverrideAuthorization] 属性。否则,[Authorize] 属性将被忽略,并且仅允许默认角色(在我的示例中为管理员),即使您指定其他角色(例如调度员等),因为全局过滤器。任何未经授权的用户都将被重定向到登录屏幕。
使用[OverrideAuthorization] 属性会导致操作忽略您设置的全局过滤器。因此,您必须在每次使用覆盖时重新应用 [Authorize] 属性,以确保操作安全。
关于整个区域和控制者
按照您的要求,要按区域进行限制,请将 [OverrideAuthorization] 和 [Authorize] 属性放在控制器上,而不是单独的操作上。