Обнаружение и авторизация Razor Pages

Я разрабатываю веб-приложение с помощью ASP.NET Core 3.0 и Razor Pages. Я хочу добавить функцию, которая позволяет пользователям выполнять поиск по имени страницы - предположим, что пользователь ищет «пароль», а результат - «Изменить пароль», что является страницей Razor.

Я предполагаю, что модели страниц будут выглядеть так:

[SearchablePage(Name="Manage Account", Keywords="password,username,change")]
public class ManageAccountModel : PageModel
{
   ...
}

Пока мне удалось обнаружить страницы, введя IActionDescriptorCollectionProvider и выполнив поиск PageActionDescriptor элементов. Это покажет мне все страницы, которые есть в приложении.

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

Я также пытаюсь выяснить, авторизован ли пользователь для просмотра страницы - исходит ли это от атрибута авторизации или соглашения об авторизации, настроенного в Startup.cs.

Мы будем очень благодарны за любую помощь или указатели, где искать!

Спасибо!

Обновить

Мне удалось найти IAuthorizationService, предоставленный фреймворком - документация. Теперь уловка состоит в том, чтобы получить все политики для бритвенной страницы.


person Nikolay Arhangelov    schedule 03.10.2019    source источник


Ответы (2)


У меня есть следующая страница, на которой перечислены все маршруты в моем веб-приложении. Это я использую для диагностики конечных точек. Может быть полезно использовать в качестве отправной точки. Не знаю, как получить информацию об авторизации.

public class RoutesModel : PageModel {
    private readonly IActionDescriptorCollectionProvider _actionDescriptorCollectionProvider;

    public RoutesModel(IActionDescriptorCollectionProvider actionDescriptorCollectionProvider) {
        this._actionDescriptorCollectionProvider = actionDescriptorCollectionProvider;
    }

    public List<RouteInfo> Routes { get; set; }

    public void OnGet() {
        Routes = _actionDescriptorCollectionProvider.ActionDescriptors.Items
                .Select(x => new RouteInfo {
                    Action = x.RouteValues["Action"],
                    Controller = x.RouteValues["Controller"],
                    Name = x.AttributeRouteInfo?.Name,
                    Template = x.AttributeRouteInfo?.Template,
                    Constraint = x.ActionConstraints == null ? "" : JsonConvert.SerializeObject(x.ActionConstraints)
                })
            .OrderBy(r => r.Template)
            .ToList();
    }

    public class RouteInfo {
        public string Template { get; set; }
        public string Name { get; set; }
        public string Controller { get; set; }
        public string Action { get; set; }
        public string Constraint { get; set; }
    }
}
person Brad Patton    schedule 04.10.2019

Мне удалось найти рабочее решение для этого, которое я сейчас тестировал со страницами, а не с контроллерами и представлениями.

Требуемые интерфейсы

  • IActionDescriptorCollectionProvider - предоставляет список всех страниц Razor.
  • PageLoader - загружает страницу Razor, разрешает ее политики безопасности и атрибуты класса.
  • IAuthorizationService- Определяет, авторизован ли пользователь для политики.

Шаги

Получите список всех бритвенных страниц.

var pageDescriptors = _descriptorProvider.ActionDescriptors.Items
  .OfType<PageActionDescriptor>()
  .ToArray();

Прокрутите страницы и загрузите каждую:

var compiledPage = await _pageLoader.LoadAsync(pageDescriptor);

На этом этапе вы можете выполнить некоторую обработку на основе атрибутов, добавленных в модель страницы. Обратите внимание, что любой атрибут, который вы добавляете в класс модели страницы, будет автоматически разрешен в EndpointMetadata, нет необходимости выполнять настраиваемую работу по отражению!

var pageMetadata = compiledPage.EndpointMetadata
  .OfType<PageMetadataAttribute>() // My custom attribute.
  .FirstOrDefault();

Обратите внимание, что политики и авторизация будут добавлены к метаданным страницы Razor в форме экземпляра AuthorizeAttribute.

Извлеките атрибуты авторизации, переберите их и оцените.

var authorization = compiledPage.EndpointMetadata
  .OfType<AuthorizeAttribute>()
  .ToArray();

foreach (var auth in authorization)
{
  if (!string.IsNullOrEmpty(auth.Policy))
  {
    var authResult = await _authorizationService.AuthorizeAsync(
      _httpContextAccessor.HttpContext.User,
      auth.Policy);

    if (!authResult.Succeeded) return; // Do stuff here.
}
person Nikolay Arhangelov    schedule 17.10.2019