Как мы можем установить авторизацию для всей области в ASP.NET MVC?


У меня есть административная область, и я хочу, чтобы Только администраторы входили в эту область. Я рассматривал возможность добавления атрибута Authorized к каждому контроллеру в административной области. Разве нет элегантного решения или этой функции нет в самой структуре?

изменить: Простите, я должен был упомянуть об этом раньше. Я использую пользовательский атрибут AuthorizedAttribute, полученный из AuthorizeAttribute.

6 52

6 ответов:

Web.безопасность на основе конфигурации должна быть почти никогда используется в приложении MVC. Причина этого заключается в том, что несколько URL-адресов потенциально могут попасть в контроллер и поместить эти проверки в Web.конфиг неизменно что-то упускает. Помните-контроллеры не связаны с областями, маршруты связаны с областями. Фабрика контроллеров MVC с радостью будет обслуживать контроллеры из области / папки для запросов вне области, если их нет конфликт.

например, используя структуру проекта по умолчанию, добавив административную область с AdminDefaultController, вы можете нажать этот контроллер через /Admin/AdminDefault / Index и / AdminDefault / Index.

единственное поддерживаемое решение состоит в том, чтобы поместить свой атрибут в базовый класс контроллера и гарантировать, что каждый контроллер в пределах подклассов области этот базовый класс.

Я только что исследовал этот же вопрос. Так как это не возможно обеспечить контроллеры на основе областей, более простой вариант приходит на ум.

создайте определение базового контроллера для каждой области, которая переопределяет контроллер, и добавьте к этому требования безопасности. Тогда вам просто нужно убедиться, что каждый контроллер в области переопределяет AreaController вместо контроллера. Например:

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

он по-прежнему требует, чтобы вы производили каждый контроллер в админке с этой базы,

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

но, по крайней мере, у вас есть единая точка, где вы определяете безопасность района.

Если весь ваш код администратора находится в одном контроллере, добавьте авторизацию ко всему классу.

[Authorize]
public class AdminController : Controller
{
     .......
}

Я только начал с этого... но пока это работает довольно хорошо для меня.

Я создаю пользовательский класс 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;
    }
}

в настоящее время принятый ответ не является самым безопасным решением, потому что он требует от разработчика всегда не забудьте наследовать этот новый базовый класс для любых новых контроллеров или действий ("черный список"; предоставление пользователям доступа ко всему, если действие не ограничено вручную). Это особенно вызывает проблемы, когда новые разработчики, не знакомые с вашими ритуалами, вводятся в проект. Легко забыть наследовать правильный класс контроллера, если это сделано таким образом, особенно после того, как вы отвели глаза от проекта на недели, месяцы или годы. Если разработчик забывает наследовать, не очевидно, что в проекте есть уязвимость безопасности.

более безопасным решением этой проблемы является отказ в доступе к все запросы, затем украсьте каждое действие ролями, которым разрешен доступ к действиям ("белый список"; предотвращение доступа ко всем пользователям, если не разрешено вручную). Теперь, если разработчик забывает белый правильная авторизация, пользователи дадут вам знать, и это так же просто, как смотреть на другие контроллеры для напоминания о том, как дать правильный доступ. Однако, по крайней мере, нет серьезной уязвимости безопасности.

В 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 - только аутентифицированные пользователи будут иметь доступ к домашнему контроллеру Index() метод.

public class HomeController : Controller
{
    [OverrideAuthorization]
    [Authorize] //Allow all authorized (logged in) users to use this action
    public ActionResult Index()
    {
        return View();
    }

}

Пример 3 - не прошедшим проверку подлинности пользователям (т. е. анонимным пользователям) можно разрешить доступ к методам с помощью . Это также автоматически переопределяет глобальный фильтр без необходимости

.. очень грубо я считаю, что вы хотите что-то вроде этого?

быстрое и грязное управление ролями

[Authorize(Roles = "Admins")]
public ActionResult Register()
{
  ViewData["roleName"] = new SelectList(Roles.GetAllRoles(), "roleName");
  ViewData["PasswordLength"] = MembershipService.MinPasswordLength;
  return View();
}