剃刀页面发现和授权

时间:2019-10-03 19:47:03

标签: c# razor-pages asp.net-core-3.0

我正在使用ASP.NET Core 3.0和Razor Pages开发一个Web应用程序。我要添加一个功能,该功能允许用户按页面名称进行搜索-假设用户搜索“密码”,结果为“更改密码”,即剃刀页面。

我想页面模型看起来像这样:

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

到目前为止,我通过注入IActionDescriptorCollectionProvider并寻找PageActionDescriptor项来设法进行页面发现。这将向我显示该应用程序中的所有页面。

我不确定如何进入每个页面的实际PageModel,以便确定自定义搜索属性的值。

我还试图弄清是否已授权用户以查看页面-无论是来自授权属性还是Startup.cs中配置的授权约定。

任何帮助或指针在哪里寻找,将不胜感激!

谢谢!

更新

我设法找到了框架documentation提供的IAuthorizationService。现在的诀窍是检索剃刀页面的所有策略。

2 个答案:

答案 0 :(得分:0)

我有以下页面列出了我的Web应用程序中的所有路由。我用来诊断端点。用作起点可能会很有用。我不确定您将如何获得授权信息。

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

答案 1 :(得分:0)

我设法找到了一个可行的解决方案,目前已使用Pages(而非控制器和视图)对其进行了测试。

必需的界面

  • 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();

请注意,策略和授权将以AuthorizeAttribute实例的形式添加到Razor页面元数据中。

提取授权属性,遍历它们并进行评估。

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