Переопределение контроллера AuthorizeAttribute всего за одно действие

У меня есть контроллер, украшенный атрибутом AuthorizeAttribute. Контроллер содержит несколько действий, требующих аутентификации отдельно от одного действия, которое требует некоторой пользовательской проверки подлинности, предоставляемой CustomAuthorizeAttribute.

Мой вопрос: однажды я добавил [Авторизовать] на уровне контроллера, могу ли я переопределить его (или удалить) с помощью [CustomAuthorize] только на одном действии? Или мне нужно удалить [Authorize] с уровня контроллера и добавить его отдельно для каждого другого действия?

Я прошу исключительно для удобства, потому что я ленив и не хочу украшать каждое действие с помощью AuthorizeAttribute.

[Authorize]
public class MyController : Controller {

  //requires authentication
  public ViewResult Admin() {
    return View();
  }

  //... a lot more actions requiring authentication

  //requires custom authentication
  [CustomAuthorize]  //never invoked as already failed at controller level
  public ViewResult Home() {
    return View();
  }

}

Ответ 1

Вы можете изменить Ордер, в котором выполняются атрибуты (с использованием свойства Order), но я считаю, что в этом случае они все равно будут работать, если не будут получены результаты с немедленным эффектом. Ключ должен иметь наименьший ограничивающий атрибут, применяемый на самом высоком уровне (классе), и получить более ограничительные методы. Если вы хотите, чтобы действие Home было общедоступным, например, вам нужно было бы удалить атрибут Authorize из класса и применить его к каждому из других методов.

Если действие имеет одинаковый уровень вседозволенности, но имеет другой результат, изменение порядка может быть достаточным. Например, вы обычно перенаправляете на действие Logon, но для Home вы хотите перенаправить действие About. В этом случае укажите атрибут класса Order=2 и атрибут Home Order=1.

Ответ 2

В MVC 5 вы можете переопределить авторизацию для любого действия, используя новый атрибут OverrideAuthorization. По сути, вы добавляете его к действию, конфигурация авторизации которого отличается от конфигурации, определенной в контроллере.

Вы делаете это так:

[OverrideAuthorization]
[Authorize(Roles = "Employee")]
public ActionResult List() { ... }

Более подробная информация на http://www.c-sharpcorner.com/UploadFile/ff2f08/filter-overrides-in-Asp-Net-mvc-5/

В ASP.NET Core 2.1 нет атрибута OverrideAuthorization, и единственное, что вы можете сделать, - это сделать действие анонимным, даже если это не контроллер. Дополнительная информация по адресу https://docs.microsoft.com/en-us/aspnet/core/security/authorization/roles?view=aspnetcore-2.1.

Один из вариантов - сделать это так:

[Authorize(Roles = "Admin,Employee")] // admin or employee
public class XController : Controller 
{
    [Authorize(Roles = "Admin")] // only admin
    public ActionResult ActionX() { ... }

    [AllowAnonymous] // anyone
    public ActionResult ActionX() { ... }
}

Ответ 3

Спустя слишком много времени, я нашел решение. Вам необходимо украсить свой контроллер с помощью пользовательского атрибута AuthorizeAttribute.

public class OverridableAuthorize : AuthorizeAttribute
{
    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        var action = filterContext.ActionDescriptor;
        if(action.IsDefined(typeof(IgnoreAuthorization), true)) return;

        var controller = action.ControllerDescriptor;
        if(controller.IsDefined(typeof(IgnoreAuthorization), true)) return;

        base.OnAuthorization(filterContext);
    }
}

Который может быть связан с AllowAnonymous в действии

[AllowAnonymous]

Ответ 4

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

[AllowAnonymous] 

к действию, которое вы хотите не авторизовать (затем добавьте свой настраиваемый атрибут по мере необходимости).

Смотрите комментарии /intellisense:

Представляет атрибут, который помечает контроллеры и действия, чтобы пропустить System.Web.Mvc.AuthorizeAttribute во время авторизации.