Я работаю над ASP. Net Core 3.1 веб-API.
Пользователи API из Azure AD. Пользователи могут получить доступ к API, если у них есть лицензия, каждому пользователю может быть назначено несколько лицензий, и одна и та же лицензия может быть назначена нескольким пользователям.
Клиент хочет, чтобы я структурировал маршруты API с помощью шаблона, подобного <api_url>/{licenseId}/controller/action
.
Мои контроллеры похожи на:
[Authorize]
[Route("{licenseId}/Foo")]
public class FooController : ControllerBase
{
Если я рассматриваю Лицензию как Ресурс, я могу использовать авторизацию на основе Ресурса, как подробно здесь, Это работает, но я копирую и вставляю проверку подлинности для всех действий.
Есть ли лучший способ авторизации пользователя с использованием значений маршрута?
Вот что у меня получилось far:
public class LicenseRequirement : IAuthorizationRequirement
{
public Guid LicenseId { get; private set; }
public LicenseRequirement(Guid licenseId)
{
LicenseId = licenseId;
}
}
public class LicenseAuthorizationHandler : AuthorizationHandler<LicenseRequirement>
{
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly ILogger<LicenseAuthorizationHandler> _logger;
private readonly DBContext _db;
public LicenseAuthorizationHandler(DBContext context, ILogger<LicenseAuthorizationHandler> logger, IHttpContextAccessor httpContextAccessor)
{
_logger = logger;
_db = context;
_httpContextAccessor = httpContextAccessor;
}
protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, LicenseRequirement requirement)
{
var userId = new Guid(context.User.GetUserId());
var licenseId = _httpContextAccessor.HttpContext.GetRouteData().Values["licenseId"];
if (await _db.ApiUsers.SingleOrDefaultAsync(x => x.LicenseId == new Guid(licenseId as string) && x.UserId == userId) is ApiUser user)
context.Succeed(requirement);
}
}
Теперь я немного застрял, поскольку не знаю, как настроить его в Startup.cs
и использовать его в качестве фильтра атрибута или области, создавая эти требования во время выполнения с помощью licenseId
значение маршрута.