Можно ли изменить поведение [Авторизовать] по умолчанию в ASP.NET MVC?

Мне было интересно, могу ли я переопределить поведение [Авторизация] по умолчанию в ASP.NET MVC и как я могу это сделать. Я знаю, что могу создать новый фильтр действий, сделать свой собственный атрибут и так далее; Меня просто интересует, могу ли я просто изменить поведение [Авторизовать] и заменить его работу своим собственным кодом?

Изменить: парни и девушки. Я ценю ваш вклад, но, как я уже писал, я не собираюсь вводить новый атрибут [XYZAuthorize]. Я знаю, как это сделать. Я хочу сохранить обозначение [Авторизовать], но просто изменить способ его работы.


person Alex    schedule 22.08.2009    source источник
comment
Почему вы хотите сохранить авторизованное имя атрибута и изменить его поведение? Это плохо. Люди, когда видят [Авторизовать], ожидают, что он сделает. Если вы его измените, читать код будет намного сложнее. Даже для тебя в будущем.   -  person Bruno Reis    schedule 22.08.2009
comment
Я не согласен; если вы с этим спорите, любая перегрузка / переопределение оператора или метода будет неправильной.   -  person Alex    schedule 22.08.2009
comment
@Alex: Я не согласен. Перегрузка оператора - это хорошо. Плохо злоупотреблять этим. Обычный пример: у вас есть класс Vector, вы создаете оператор +. Совершенно очевидно, что он будет делать. А как насчет оператора *? Это плохо, перекрестное произведение или скалярное произведение? Или другой вид нестандартного продукта? Итак: перегрузка - это хорошо, но очень плохо, когда вы маскируете условности.   -  person Bruno Reis    schedule 22.08.2009
comment
Не будучи экспертом, я последовал предложению Бруно Рейса использовать его как отдельный атрибут [MyCompanyNameAuthorize]. Пример того, как это сделать, можно найти на странице geekswithblogs.net/thomasthedeuce/archive. / 2009/06/25 /   -  person Colin    schedule 12.09.2013


Ответы (5)


Да, взгляните на документы MSDN для AuthorizeAttribute: http://msdn.microsoft.com/en-us/library/system.web.mvc.authorizeattribute.aspx.

По сути, вы можете переопределить метод OnAuthorization () и настроить его поведение. Для атрибута есть и другие виртуальные методы.

РЕДАКТИРОВАТЬ: как указал Бруно, вы можете переопределить метод AuthorizeCore (). Основное отличие состоит в том, что AuthorizeCore () принимает HttpContextBase, а OnAuthorization () принимает AuthorizationContext. Экземпляр AuthorizationContext предоставляет вам дополнительную информацию, такую ​​как Контроллер, RequestContext и RouteData. Он также позволяет указать ActionResult.

AuthorizeCore () более ограничен в отношении информации, к которой вы можете получить доступ, а также результата, который вы можете вернуть, но если вам нужно авторизовать кэшированные данные, тогда ваша логика должна обрабатывать случай, когда у вас нет каких-либо из этих дополнительных данных ( поскольку данные обслуживаются из кеша до того, как запрос будет маршрутизирован через конвейер MVC).

Как всегда, вам необходимо понимать свой сценарий, доступные инструменты и компромиссы между ними.

person Brannon    schedule 22.08.2009
comment
AuthorizeAttribute не содержит метода OnAuthorize. Вы имеете в виду OnAuthorization ()? В любом случае, вы не должны изменять его, если только вы не хотите головной боли при реализации кеширования, поскольку это единственный метод (OnAuthorization), который этим занимается. - person Bruno Reis; 22.08.2009

Вы можете создать подкласс фильтра AuthorizeAttribute и поместить в него свою логику.

Посмотрим на пример. Допустим, вы хотите всегда разрешать локальные подключения. Однако, если это удаленное соединение, вы хотели бы сохранить обычную логику авторизации.

Вы можете сделать что-то вроде:

public class LocalPermittedAuthorizeAttribute : AuthorizeAttribute
{
    protected override bool AuthorizeCore(HttpContextBase httpContext)
        {
            return (httpContext.Request.IsLocal || base.AuthorizeCore(httpContext)));
        }
}

Или вы всегда можете авторизовать определенный удаленный адрес (например, ваш компьютер).

Вот и все!

Изменить: забыл упомянуть, вы будете использовать его так же, как и фильтр AuthorizeAttribute:

class MyController : Controller
{
    [LocalPermittedAuthorize]
    public ActionResult Fire()
    {
        Missile.Fire(Datetime.Now);
    }
}
person Bruno Reis    schedule 22.08.2009

Реализуйте собственный поставщик ролей и настройте приложение на его использование. Тогда атрибут авторизации будет учитывать ваш код авторизации.

person twk    schedule 22.08.2009

Я вижу только 2 способа: переопределить метод AuthorizeAttribute.OnAuthorization или создать свой собственный атрибут авторизации с нуля.

1) очень просто:

public class CustomAuthorizeAttribute : AuthorizeAttribute
{
    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        base.OnAuthorization(filterContext);

        /// your behavior here
    }
}

2) тоже легко - просто посмотрите на источник ASP.NET MVC, файл AuthorizeAttribute.cs

person eu-ge-ne    schedule 22.08.2009
comment
Вам следует избегать создания атрибута авторизации с нуля, если вы не хотите головной боли при реализации кэширования ... атрибут авторизации из ASP.NET MVC уже имеет дело с этим аспектом. - person Bruno Reis; 22.08.2009

Кажется, вы можете реализовать собственный фильтр как обычно (и наследовать AuthorizeAttribute, если хотите), а затем создать новый ActionInvoker, который наследует ControllerActionInvoker и переопределяет GetFilters. В GetFilters вы вызываете base.GetFilters() для получения списка фильтров, перебираете AuthorizationFilters и заменяете вызовы AuthorizeFilter вызовами вашего настраиваемого фильтра.

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

person svinto    schedule 22.08.2009
comment
Зачем нужен пользовательский ActionInvoker только для простого фильтра авторизации? - person Bruno Reis; 22.08.2009
comment
@Bruno: Потому что, похоже, нет другого способа заменить фильтр фреймворка собственным, просто чтобы создать новые. - person svinto; 22.08.2009
comment
Но ... зачем нужно заменять фреймворк? Посмотрите мой комментарий к вопросу. Это глупо. - person Bruno Reis; 22.08.2009
comment
@Bruno: Допустим, у вас есть куча уже написанных контроллеров от какого-то другого проекта / разработчика / того, что вы либо не хотите, либо не можете изменить из-за отсутствия исходного кода. Вы хотите использовать SQL Server не для хранения данных о пользователях и ролях, а для чего-то еще. И вы бы предпочли не реализовывать настраиваемые поставщики членства и ролей, потому что они раздуты, и вы ленивы. Вот когда! Вероятно, лучше создать настраиваемые поставщики или создать настраиваемые (новые) атрибуты, но могут возникать ситуации, когда требуется заменить вызовы AuthorizationFilter. - person svinto; 22.08.2009
comment
@svinto можешь показать пример замены AuthorizeFilter? - person Chris Moutray; 09.07.2012