Авторизация: как обрабатывать несколько (дюжину или более) требований - PullRequest
0 голосов
/ 29 мая 2020

У меня есть набор таблиц в нашей базе данных с пользователями, разрешениями и объединением, который отображает, какие пользователи имеют какие разрешения.

Глядя на документы , ниже приводится пример того, как политики и требования устанавливаются на Startup:

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllersWithViews();
    services.AddRazorPages();
    services.AddAuthorization(options =>
    {
        options.AddPolicy("AtLeast21", policy =>
            policy.Requirements.Add(new MinimumAgeRequirement(21)));
    });
}

И здесь является примером обработчика для нескольких требований:

using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using PoliciesAuthApp1.Services.Requirements;

public class PermissionHandler : IAuthorizationHandler
{
    public Task HandleAsync(AuthorizationHandlerContext context)
    {
        var pendingRequirements = context.PendingRequirements.ToList();

        foreach (var requirement in pendingRequirements)
        {
            if (requirement is ReadPermission)
            {
                if (IsOwner(context.User, context.Resource) ||
                    IsSponsor(context.User, context.Resource))
                {
                    context.Succeed(requirement);
                }
            }
            else if (requirement is EditPermission ||
                     requirement is DeletePermission)
            {
                if (IsOwner(context.User, context.Resource))
                {
                    context.Succeed(requirement);
                }
            }
        }

        //TODO: Use the following if targeting a version of
        //.NET Framework older than 4.6:
        //      return Task.FromResult(0);
        return Task.CompletedTask;
    }

    private bool IsOwner(ClaimsPrincipal user, object resource)
    {
        // Code omitted for brevity

        return true;
    }

    private bool IsSponsor(ClaimsPrincipal user, object resource)
    {
        // Code omitted for brevity

        return true;
    }
}

Я намерен проверить таблицы базы данных в обработчике, чтобы убедиться, что у пользователя есть параметр, соответствующий политике. Чтобы проверить, может ли пользователь загружать файлы, политика может выглядеть следующим образом:

    services.AddAuthorization(config =>
    {
        config.AddPolicy("CanUploadFiles", policy => policy.Requirements.Add(new CanDoRequirement("CanUploadFiles")));
    });

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

Вопрос: Учитывая, что у меня может быть 10-20 отдельных разрешений «CanDo…» в нашей таблице, есть ли лучший способ настроить их, чем отдельные строки в AddAuthorization()?

1 Ответ

1 голос
/ 30 мая 2020

Ну, мне не известны какие-либо ярлыки при настройке требований и политик 20-i sh, которые удаляли бы отдельные строки при запуске, но вы могли бы подумать о реализации своего рода авторизации на основе настраиваемых ресурсов, а не политики основанный на политике, являющийся декларативным. Декларативное значение означает, что политика настроена заранее. Вот так: [Authorize("policy")].

Используя императивную авторизацию, а не декларативную, вы избавитесь от необходимости настраивать x количество политик. Вместо того, чтобы говорить «Авторизовать этот метод», вы позволяете структуре позаботиться об авторизации.

Учитывайте следующие требования

Пользователь должен быть аутентифицирован. Этот пользователь может загрузить файл, только если он удовлетворяет CanUploadFiles, которое является логическим для записи пользователя в базе данных.

Теперь рассмотрим следующий пример

Вы создали свой собственный ICustomAuthorizationHandler, несколько похожий к ASP. NET Core IAuthorizationHandler, за исключением того, что вы не будете удовлетворять политике, но вместо этого вы передадите ему 'CanDoPermission', и он вернет true или false, если этот пользователь имеет эту спецификацию c 'flag'.

public class FileController : Controller
{
    private ICustomAuthorizationService _authService
    public FileController(ICustomAuthorizationService authService)
    {
        _authService = authService;
    }

    [Authorize]
    public async Task<IActionResult> Upload(IFormFile file)
    {
        var authResult = await _authService.AuthorizeAsync(User, "CanDoUpload");
        if (!authResult.Succeeded)
        {
            return new ForbidResult();
        }
        // Process upload
        return View();
    }
}

Таким образом, не должно быть политик или требований, настроенных для проверки того, может ли пользователь загрузить файл. Но вам нужно будет позаботиться о многих вещах, которые вы получаете «бесплатно», просто выбрав политики и настроив их в AddAuthorization.

...