ASP.NET 5 Разрешить использование двух или нескольких политик

Можно ли применить авторизацию против двух или более политик? Я использую ASP.NET 5, rc1.

[Authorize(Policy = "Limited,Full")]
public class FooBarController : Controller
{
    // This code doesn't work
}

Если нет, как я могу достичь этого без использования политик? Существуют две группы пользователей, которые могут получить доступ к этому контроллеру: "Полный" и "Ограниченный". Пользователи могут принадлежать "Полному" или "Ограниченному", или и тому и другому. Для доступа к этому контроллеру требуется только принадлежность к одной из двух групп.

Ответ 1

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

Вы должны оценить условия OR в рамках одной политики. Но вам не нужно указывать его как OR в одном обработчике. У вас может быть требование, которое имеет более одного обработчика. Если какой-либо из обработчиков успешно выполняет флаг, то требование выполняется. См. Шаг 6 в Авторизация.

Ответ 2

После настройки новой политики "LimitedOrFull" (при условии, что они совпадают с именами типов утверждений) создайте такое требование:

options.AddPolicy("LimitedOrFull", policy =>
    policy.RequireAssertion(context =>
        context.User.HasClaim(c =>
            (c.Type == "Limited" ||
             c.Type == "Full"))));

https://docs.microsoft.com/en-us/aspnet/core/security/authorization/policies?view=aspnetcore-2.1#using-a-func-to-fulfill-a-policy

Ответ 4

Мое решение для ASP.Net Core состояло в том, чтобы успешно выполнить все ожидающие требования, если он успешен, и потерять контекст только в том случае, если это не удалось. Я основал решение на следующих предположениях: 1. Порядок требований всегда от действия вверх (таким образом, сначала требование - это действие, затем - на контроллере, затем - на базовом контроллере) 2. Выполнение всех ожидающих требований в контексте авторизации не остановит их итерацию. 3. Если все требования выполнены, то контекст имеет HasSucceded true

Итак, вот код:

if (condition(requirement)) {
  context.PendingRequirements.OfType<MyRequirement>().ToList().ForEach(context.Succeed);
} else if (!context.HasSucceeded) {
  context.Fail();
}

Примеры:

  1. у контроллера есть политика, добавляющая требование администратора, а действие имеет политику для пользователя. Когда пользователь вызывает действие, обработчик авторизации будет иметь два требования: Пользователь и Администратор. Первое требование будет выполнено успешно (user = user), и поэтому приведенный выше код выполнит все требования, установив context.HasSucceeded true. Второе требование не будет выполнено, но оно не будет выполнено.

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

Это немного хакерский, но меньше, чем мой первый вариант, который был что-то вроде:

var requirement = context.Requirements.OfType<MyRequirement>().First();
if (condition(requirement)) {
  context.Succeed(requirement);
} else {
  context.Fail();
}

Вы могли бы предпочесть этот.

Обновление: я понял, что второй вариант немного более надежен, поскольку у вас могут быть различные типы требований и контекста. Возможно, значение HasSucceded не соответствует действительности (пока).

Ответ 5

попробуйте использовать роль вместо

[Authorize(Role = "Limited,Full")]