The current accepted answer is not the safest solution, because it requires the developer to always remember to inherit this new base class for any new controllers or actions (a βblack listβ, allowing users to access everything if the action is not limited manually). This is especially problematic when new developers unfamiliar with your rituals are introduced into the project. It is easy to forget to inherit the correct controller class if this is done so, especially after you have taken your eyes off the project for weeks, months or years. If the developer forgets to inherit, it is not obvious that the project has a security vulnerability.
A safer solution to this problem is to deny access to all requests, and then decorate each action with roles that are allowed access to actions ("whitelisting"; preventing access to all users except manually is allowed). Now, if the developer forgets to include the correct authorization whitelist, users will let you know as easily as looking at other controllers to remind them how to ensure proper access. However, at least there is no significant security vulnerability.
In the App_Start / FilterConfig.cs file, change the FilterConfig class:
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" }); }
This makes all actions inaccessible if the user is not registered as an administrator. Then for each action that you want another authorized user to access, you simply decorate it with [OverrideAuthorization] and [Authorize] .
In your business logic, this allows you to use the Authorize attribute in various ways, without worrying that unauthorized users can access any function. The following are some examples.
Example 1 For logon only, Administrators and Dispatcher users will have access to the Index() methods of Get and 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(...); } }
Example 2 Access to the Home controller Index() method will be allowed only to authorized users.
public class HomeController : Controller { [OverrideAuthorization] [Authorize]
Example 3 Unauthorized users (that is, anonymous users) may be allowed to access methods using the [AllowAnonymous] attribute. It also automatically cancels the global filter without requiring the [OverrideAuthorization] attribute.
// 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) { ... }
Example 4 Only administrators will be allowed to access methods that do not need the [Authorize] attribute.
public class LocationsController : Controller {
Some notes.
You must use the [OverrideAuthorization] attribute if you want to restrict access to a specific action to certain roles. Otherwise, the properties of the [Authorize] attribute will be ignored, and only the default role will be allowed (administrator in my example), even if you specify other roles (for example, dispatcher, etc.) due to the global filter. Any unauthorized users will be redirected to the login screen.
Using the [OverrideAuthorization] attribute causes the action to ignore the set global filter. Therefore, you must reapply the [Authorize] attribute whenever you use redefinition so that the action remains safe.
For whole areas and controllers
To limit the scope as you ask, place the [OverrideAuthorization] and [Authorize] attributes on the controller instead of separate actions.