Razor 页面发现和授权
Razor Pages Discovery and Authorization
我正在使用 ASP.NET Core 3.0 和 Razor Pages 开发网络应用程序。我想添加一个功能,允许用户按页面名称搜索 - 假设用户搜索 'password',结果是 'Change Password',这是一个 Razor 页面。
我想页面模型应该是这样的:
[SearchablePage(Name="Manage Account", Keywords="password,username,change")]
public class ManageAccountModel : PageModel
{
...
}
到目前为止,我设法通过注入 IActionDescriptorCollectionProvider
并查找 PageActionDescriptor
项来发现页面。这会显示应用程序中的所有页面。
我不确定如何获取每个页面的实际 PageModel
class,以便确定自定义搜索属性的值。
我也在尝试弄清楚用户是否有权查看该页面 - 是来自授权属性还是来自 [=43= 中配置的授权约定].
我们将不胜感激任何帮助或指导!
谢谢!
更新
我设法找到了框架提供的 IAuthorizationService
- documentation。现在的诀窍是检索剃刀页面的所有策略。
我有以下页面列出了我的网络应用程序中的所有路由。我用来诊断端点的。用作起点可能很有用。我不确定您将如何获得授权信息。
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; }
}
}
我设法找到了一个可行的解决方案,目前我已经使用页面而不是控制器和视图对其进行了测试。
所需接口
IActionDescriptorCollectionProvider
- 提供所有 Razor 页面的列表。
PageLoader
- 加载 Razor 页面,解析其安全策略和 class 属性。
IAuthorizationService
- 确定用户是否有权使用策略。
步骤
获取所有剃须刀页面的列表。
var pageDescriptors = _descriptorProvider.ActionDescriptors.Items
.OfType<PageActionDescriptor>()
.ToArray();
遍历页面并加载每个页面:
var compiledPage = await _pageLoader.LoadAsync(pageDescriptor);
此时您可以根据添加到页面模型的属性进行一些处理。请注意,您添加到页面模型 class 的任何属性将在 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.
}
我正在使用 ASP.NET Core 3.0 和 Razor Pages 开发网络应用程序。我想添加一个功能,允许用户按页面名称搜索 - 假设用户搜索 'password',结果是 'Change Password',这是一个 Razor 页面。
我想页面模型应该是这样的:
[SearchablePage(Name="Manage Account", Keywords="password,username,change")]
public class ManageAccountModel : PageModel
{
...
}
到目前为止,我设法通过注入 IActionDescriptorCollectionProvider
并查找 PageActionDescriptor
项来发现页面。这会显示应用程序中的所有页面。
我不确定如何获取每个页面的实际 PageModel
class,以便确定自定义搜索属性的值。
我也在尝试弄清楚用户是否有权查看该页面 - 是来自授权属性还是来自 [=43= 中配置的授权约定].
我们将不胜感激任何帮助或指导!
谢谢!
更新
我设法找到了框架提供的 IAuthorizationService
- documentation。现在的诀窍是检索剃刀页面的所有策略。
我有以下页面列出了我的网络应用程序中的所有路由。我用来诊断端点的。用作起点可能很有用。我不确定您将如何获得授权信息。
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; }
}
}
我设法找到了一个可行的解决方案,目前我已经使用页面而不是控制器和视图对其进行了测试。
所需接口
IActionDescriptorCollectionProvider
- 提供所有 Razor 页面的列表。PageLoader
- 加载 Razor 页面,解析其安全策略和 class 属性。IAuthorizationService
- 确定用户是否有权使用策略。
步骤
获取所有剃须刀页面的列表。
var pageDescriptors = _descriptorProvider.ActionDescriptors.Items
.OfType<PageActionDescriptor>()
.ToArray();
遍历页面并加载每个页面:
var compiledPage = await _pageLoader.LoadAsync(pageDescriptor);
此时您可以根据添加到页面模型的属性进行一些处理。请注意,您添加到页面模型 class 的任何属性将在 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.
}