Подтвердить что ты не робот

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

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

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

4b9b3361

Ответ 1

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

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

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

Ответ 2

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

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

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

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

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

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

Ответ 3

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

Я создаю собственный класс 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;
    }
}

Ответ 4

Если весь ваш код администратора находится в одном контроллере, добавьте Authorize для всего класса.

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

Ответ 5

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

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

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

Ответ 6

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

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

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