Как мы можем установить авторизацию для всей области в ASP.NET MVC? - PullRequest
53 голосов
/ 23 февраля 2010

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

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

Ответы [ 6 ]

53 голосов
/ 23 февраля 2010

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

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

.

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

45 голосов
/ 25 января 2013

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

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

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

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

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

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

14 голосов
/ 11 сентября 2015

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

Я создаю собственный класс 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;
    }
}
13 голосов
/ 23 февраля 2010

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

[Authorize]
public class AdminController : Controller
{
     .......
}
5 голосов
/ 09 ноября 2017

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

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

В файле 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() контроллера Home.

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] на контроллер вместо отдельных действий.

0 голосов
/ 23 февраля 2010

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

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

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