Обнаружение и авторизация бритвенных страниц - PullRequest
0 голосов
/ 03 октября 2019

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

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

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

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

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

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

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

Спасибо!

Обновление

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

Ответы [ 2 ]

0 голосов
/ 17 октября 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.
}
0 голосов
/ 04 октября 2019

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

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; }
    }
}
...