How can we set authorization for an entire area in ASP.NET MVC?

I have an admin area and I want only admins to enter this area. I decided to add the Authorized attribute to each controller in the admin area. Is there no elegant solution or is this feature absent in the structure itself?

EDIT: Sorry, I should have mentioned this before. I am using a custom authorized attribute derived from AuthorizeAttribute.

+51
authorization asp.net-mvc-2 asp.net-mvc-areas
Feb 23 '10 at 15:08
source share
6 answers

Security in Web.config should almost never be used in an MVC application. The reason for this is that several URLs can potentially get into the controller, and if these checks are checked in Web.config they invariably miss. Remember - controllers are not connected to areas, routes are connected to areas. The MVC factory controller will happily serve controllers from a region / folder for non-region requests if there is no conflict.

For example, using the default project structure, adding an admin area using the AdminDefaultController, you can click this controller through / Admin / AdminDefault / Index and / AdminDefault / Index.

The only supported solution is to put your attribute in the base class of the controller and make sure that each controller in the scope subclasses of this base class.

+51
Feb 23 '10 at 17:47
source share

I just studied the same issue. Since it is not possible to protect area-based controllers, you will need a simpler option.

Create a base controller definition for each area that overrides the controller, and add security requirements for this. Then you just need to ensure that each controller in the area overlaps the AreaController instead of the Controller. For example:

/// <summary> /// Base controller for all Admin area /// </summary> [Authorize(Roles = "Admin")] public abstract class AdminController : Controller { } 

It is still required that you remove each controller in the administrator area from this database,

 public class HomeController : AdminController { // .. actions } 

but at least you have one point where you define security for this area.

+42
Jan 25 '13 at 8:34
source share

I just started with this ... but so far it works very well for me.

I create my own class AuthorizeAttribute and add it to the RegisterGlobalFilters function.

In CustomAuthorizeAttribute, I test various conditions based on the area in which it is located.

 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; } } 
+13
Sep 11 '15 at 1:16
source share

If all of your admin code is in one controller, add Authorize for the entire class.

 [Authorize] public class AdminController : Controller { ....... } 
+12
23 Feb 2018-10-23T00
source share

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] //Allow all authorized (logged in) users to use this action public ActionResult Index() { return View(); } } 

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 { // GET: Locations public ActionResult Index() { //Business logic here. return View(...); } } 

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.

0
Nov 09 '17 at 17:49
source share

.. very rude, I think you want something like this?

Quick and dirty role management

 [Authorize(Roles = "Admins")] public ActionResult Register() { ViewData["roleName"] = new SelectList(Roles.GetAllRoles(), "roleName"); ViewData["PasswordLength"] = MembershipService.MinPasswordLength; return View(); } 
-5
Feb 23 '10 at 15:10
source share



All Articles