Я пытаюсь сделать пользовательский атрибут авторизации в ASP.NET Core. В предыдущих версиях можно было переопределить bool AuthorizeCore(HttpContextBase httpContext)
. Но это больше не существует в AuthorizeAttribute
.
Каков текущий подход к созданию пользовательского AuthorizeAttribute?
Что я пытаюсь сделать: я получаю идентификатор сеанса в авторизации заголовка. По этому идентификатору я узнаю, является ли конкретное действие действительным.
Ответы:
Подход, рекомендованный основной группой ASP.Net, заключается в использовании нового дизайна политики, который полностью описан здесь . Основная идея нового подхода заключается в использовании нового атрибута [Authorize] для обозначения «политики» (например,
[Authorize( Policy = "YouNeedToBe18ToDoThis")]
когда политика зарегистрирована в Startup.cs приложения для выполнения некоторого блока кода (т. Е. Обеспечения того, чтобы у пользователя было требование о возрасте). где возраст 18 лет и старше).Разработка политики является отличным дополнением к этой структуре, и команда разработчиков ASP.Net Security Core заслуживает похвалы за ее внедрение. Тем не менее, это не подходит для всех случаев. Недостатком этого подхода является то, что он не обеспечивает удобного решения для наиболее распространенной необходимости простого утверждения, что для данного контроллера или действия требуется данный тип заявки. В случае, когда приложение может иметь сотни отдельных разрешений, управляющих операциями CRUD на отдельных ресурсах REST («CanCreateOrder», «CanReadOrder», «CanUpdateOrder», «CanDeleteOrder» и т. Д.), Новый подход требует либо повторяющихся однозначных одно сопоставление между именем политики и именем заявки (например,
options.AddPolicy("CanUpdateOrder", policy => policy.RequireClaim(MyClaimTypes.Permission, "CanUpdateOrder));
) или написание некоторого кода для выполнения этих регистраций во время выполнения (например, прочитать все типы утверждений из базы данных и выполнить вышеупомянутый вызов в цикле). Проблема с этим подходом для большинства случаев состоит в том, что это ненужные накладные расходы.Хотя группа ASP.Net Core Security рекомендует никогда не создавать свое собственное решение, в некоторых случаях это может быть наиболее разумным вариантом для начала.
Ниже приведена реализация, которая использует IAuthorizationFilter, чтобы предоставить простой способ выражения требования заявки для данного контроллера или действия:
источник
new ForbidResult()
не работает (вызывает исключение / 500), потому что у него нет связанной схемы авторизации. Что бы я использовал для этого случая?Я сотрудник службы безопасности asp.net.
Во-первых, позвольте мне извиниться, что ничего из этого еще не задокументировано за пределами образца музыкального магазина или модульных тестов, и все это все еще дорабатывается с точки зрения открытых API.Подробная документация здесь .Мы не хотим, чтобы вы писали пользовательские атрибуты авторизации. Если вам нужно сделать это, мы сделали что-то не так. Вместо этого вы должны писать требования авторизации .
Авторизация действует в соответствии с идентификационными данными. Личности создаются путем аутентификации.
В комментариях вы говорите, что хотите проверить идентификатор сессии в заголовке. Ваш идентификатор сессии будет основой для идентификации. Если вы хотите использовать
Authorize
атрибут, вы должны написать промежуточное программное обеспечение для аутентификации, чтобы взять этот заголовок и превратить его в аутентифицированныйClaimsPrincipal
. Затем вы проверите это внутри требования авторизации. Требования к авторизации могут быть настолько сложными, насколько вам нравится, например, вот тот, который берет заявление о дате рождения на текущую личность и разрешает, если пользователь старше 18 лет;Тогда в вашей
ConfigureServices()
функции вы бы подключить егоИ наконец, примените его к контроллеру или методу действия с
источник
ManageStore
образец требования от Music Store. Как видно из примера, существует только один способ «разрешить все или ничего». Должны ли мы создавать новую политику для каждой возможной перестановки? то есть «Пользователи / Чтение», «Пользователи / Создать», «Пользователи / AssignRole», «Пользователи / Удалить», если мы хотим детализированные утверждения? Звучит так, как будто все работает, чтобы заставить его работать, и изобилие политик для управления претензиями, а не[ClaimsAutzorization("User", "Read", "Create", "Delete", "Assign")]
атрибутами?[CustomAuthorize(Operator.And, Permission.GetUser, Permission.ModifyUser)]
. Я мог бы использовать один пользовательский атрибут бесконечным количеством способов, просто изменив параметры конструктора.IAuthorizeData.Policy
) и настраиваемые поставщики политик для преодоления этого вопиющего упущения, а не решать его в рамках. Я думал, что мы не должны создавать наши собственные реализации? У некоторых из нас не было выбора, кроме как заново внедрить авторизацию с нуля (опять же), и на этот раз даже без преимущества старогоAuthorize
атрибута Web API . Теперь мы должны сделать это на уровне фильтра действий или промежуточного программного обеспечения.Кажется, что с ASP.NET Core 2 вы можете снова наследовать
AuthorizeAttribute
, вам просто нужно также реализоватьIAuthorizationFilter
(илиIAsyncAuthorizationFilter
):источник
OnAuthorization
реализации требуется ожидание асинхронного метода, вы должны реализовать ее,IAsyncAuthorizationFilter
вIAuthorizationFilter
противном случае ваш фильтр будет выполняться синхронно, а действие вашего контроллера будет выполняться независимо от результата фильтра.Основываясь на ответе Дерека Грира GREAT , я сделал это с помощью перечислений.
Вот пример моего кода:
источник
Вы можете создать свой собственный AuthorizationHandler, который будет находить пользовательские атрибуты в ваших контроллерах и действиях и передавать их в метод HandleRequirementAsync.
Затем вы можете использовать его для любых пользовательских атрибутов, которые вам нужны на ваших контроллерах или действиях. Например, чтобы добавить требования разрешения. Просто создайте свой собственный атрибут.
Затем создайте требование для добавления в вашу политику
Затем создайте AuthorizationHandler для своего пользовательского атрибута, унаследовав AttributeAuthorizationHandler, который мы создали ранее. Он будет передан IEnumerable для всех ваших пользовательских атрибутов в методе HandleRequirementsAsync, собранных из вашего контроллера и Action.
И наконец, в вашем методе Startup.cs ConfigureServices добавьте свой собственный AuthorizationHandler в службы и добавьте свою Политику.
Теперь вы можете просто украсить свои контроллеры и действия с помощью пользовательского атрибута.
источник
Легко: не создавай свой
AuthorizeAttribute
.Для сценариев с чистой авторизацией (например, ограничение доступа только для определенных пользователей) рекомендуется использовать новый блок авторизации: https://github.com/aspnet/MusicStore/blob/1c0aeb08bb1ebd846726232226279bbe001782e1/samples/MusicStore/Startup.cs#84 -L92
Для аутентификации лучше всего работать на уровне промежуточного программного обеспечения.
Чего именно вы пытаетесь достичь?
источник
Если кто-то просто хочет проверить токен на этапе авторизации, используя текущие методы обеспечения безопасности, которые вы можете,
добавьте это в свой Startup / ConfigureServices
и это в вашей кодовой базе,
Если код не доходит,
context.Succeed(...)
он все равно потерпит неудачу (401).И тогда в ваших контроллерах вы можете использовать
источник
Современный способ - АутентификацияHandlers
в startup.cs добавить
IUserService - это сервис, который вы делаете, где у вас есть имя пользователя и пароль. в основном он возвращает класс пользователя, который вы используете для сопоставления ваших утверждений.
Затем вы можете запросить эти утверждения и любые сопоставленные вами данные, а их немало, взгляните на класс ClaimTypes.
Вы можете использовать это в методе расширения, чтобы получить любое из отображений
Этот новый способ, я думаю, лучше, чем
источник
На момент написания этой статьи я считаю, что это можно сделать с помощью интерфейса IClaimsTransformation в asp.net core 2 и выше. Я только что реализовал подтверждение концепции, которое достаточно доступно для публикации здесь.
Чтобы использовать это в вашем контроллере, просто добавьте соответствующие
[Authorize(Roles="whatever")]
методы.В нашем случае каждый запрос включает заголовок авторизации, который является JWT. Это прототип, и я думаю, что мы сделаем что-то очень близкое к этому в нашей производственной системе на следующей неделе.
Будущие избиратели, при голосовании учитывайте дату написания. На сегодняшний день, это
works on my machine.
™ Вы, вероятно, захотите больше обработки ошибок и регистрации в вашей реализации.источник
Для авторизации в нашем приложении. Мы должны были вызвать сервис на основе параметров, переданных в атрибуте авторизации.
Например, если мы хотим проверить, может ли вошедший в систему врач просматривать записи о пациентах, мы передадим «View_Appointment» для настраиваемого атрибута авторизации и проверим это право в службе БД, и на основании результатов мы будем проверять. Вот код для этого сценария:
И в действии API мы используем это так:
источник
Принятый ответ ( https://stackoverflow.com/a/41348219/4974715 ) не является реально поддерживаемым или подходящим, поскольку в качестве утверждения используется «CanReadResource» (но, по сути, это должна быть политика в действительности, IMO). Подход к ответу не подходит в том смысле, в котором он использовался, потому что если метод действия требует много разных настроек утверждений, то с этим ответом вам придется многократно писать что-то вроде ...
Итак, представьте, сколько потребуется кодирования. В идеале «CanReadResource» должен быть политикой, которая использует много утверждений, чтобы определить, может ли пользователь прочитать ресурс.
Что я делаю, я создаю свою политику как перечисление, а затем перебираю и устанавливаю требования следующим образом ...
Класс DefaultAuthorizationRequirement выглядит так ...
Обратите внимание, что приведенный выше код может также включить предварительное сопоставление пользователя с политикой в вашем хранилище данных. Таким образом, при составлении заявок для пользователя вы в основном извлекаете политики, которые были предварительно сопоставлены с пользователем прямо или косвенно (например, потому что у пользователя есть определенное значение заявки, и это значение заявки было идентифицировано и сопоставлено с политикой, например, что он обеспечивает автоматическое сопоставление для пользователей, которые также имеют это значение утверждения), и включает политики в качестве утверждений, так что в обработчике авторизации вы можете просто проверить, содержат ли утверждения пользователя требование. Политика в качестве элемента значения утверждения в их претензии. Это для статического способа выполнения требования политики, например, требование «Имя» носит статический характер. Так,
Динамическое требование может касаться проверки возрастного диапазона и т. Д., А политики, в которых используются такие требования, не могут быть предварительно сопоставлены пользователям.
Пример проверки заявок на динамическую политику (например, чтобы проверить, не старше ли пользователя 18 лет) уже находится на ответе, заданном @blowdart ( https://stackoverflow.com/a/31465227/4974715 ).
PS: я набрал это на моем телефоне. Простите за любые опечатки и отсутствие форматирования.
источник