我如何从 appsettings 为 Blazor 中的授权视图标签或属性动态设置允许的角色或策略?

How would I dynamically set the allowed Role or Policy for an Authorize View tag or attribute in Blazor from appsettings?

我正在尝试为几个应用程序创建一个共享布局。这些应用程序是 Blazor 服务器端应用程序。这个布局有一个小菜单,可以通过 appsettings 文件进行配置。其中一项要求是我们能够根据应用程序设置中的 Active Directory 组列表显示或隐藏某些菜单项。下面是 JSON 设置的示例。

{
  "MenuItemName":"Protected Menu Item",
  "AllowedGroups": ["Administrator", "SpecialGroup", "SpecialGroup2"]
}

我认为我们需要在页面上使用 标记 and/or 或 [Authorized] 属性,以确保用户无法导航到该页面。

我实际上如何动态填写这些标签?例如,从 Microsoft 文档 (https://docs.microsoft.com/en-us/aspnet/core/blazor/security/?view=aspnetcore-5.0#authorize-attribute-1) 中获取以下示例。我如何用 Appsettings.json 中的设置替换 Roles="admin, superuser"?

<AuthorizeView Roles="admin, superuser">
    <p>You can only see this if you're an admin or superuser.</p>
</AuthorizeView>

在另一个使用 [Authorized] 属性的示例中,我将如何从 appsetings 动态填充 Roles = "admin, superuser" 部分?

@page "/"
@attribute [Authorize(Roles = "admin, superuser")]

<p>You can only see this if you're in the 'admin' or 'superuser' role.</p>

属性在构建时嵌入到程序集中。一旦构建了 project/DLL,您就无法再次更改该值。

您需要执行运行时授权。由于您正在尝试检查角色,因此注入配置并检查用户是否具有任何角色:

@inject IConfiguration Configuration
var isAllowed = Configuration.GetSection("AllowedGroups")
    .Get<string[]>()
    .Any(group => user.IsInRole(group));

更多信息

您可以设置一项政策来执行此操作: 这只是从 appsettings.json 中的 "AllowedGroups" 中读取一个字符串数组,但它演示了基础知识。

{
  "AllowedGroups": [ "Administrator", "Moderator" ]
}
public class HasRolesFromConfigRequirement : IAuthorizationRequirement
{
    internal string[] allowedGroups;
    public HasRolesFromConfigRequirement(string[]? allowedGroups) => this.allowedGroups = allowedGroups;
}
public class HasRolesFromConfigHandler : AuthorizationHandler<HasRolesFromConfigRequirement>
{
    protected override Task HandleRequirementAsync(
        AuthorizationHandlerContext context,
        HasRolesFromConfigRequirement requirement)
    {
        var rolesRequired = requirement.allowedGroups;
        if (rolesRequired is null)
        {
            context.Fail();
        }
        else
        {
            var hasRequiredRole = rolesRequired.Where(role => context.User.IsInRole(role)).Any();
            if(hasRequiredRole)
            {
                context.Succeed(requirement);
            }
            else
            {
                context.Fail();
            }
        }
        return Task.CompletedTask;
    }
}
public static class AuthorizationOptionsPolicyExtensions
{
    public static void AddPolicies(this IServiceCollection services, IConfiguration configuration)
    {
        services.AddScoped<IAuthorizationHandler, HasRolesFromConfigHandler>();
        services.AddAuthorizationCore(options => options.ConfigurePolicies(configuration));
    }

    public static AuthorizationOptions ConfigurePolicies(this AuthorizationOptions options, IConfiguration configuration)
    {
        var localConfiguration = configuration.Get<LocalConfiguration>();
        options.AddPolicy("HasARequiredRole", policy => policy.Requirements.Add(new HasRolesFromConfigRequirement(localConfiguration.AllowedGroups)));
        return options;
    }

}
<AuthorizeView Policy="HasARequiredRole">
    <div>
        Has A Required Role
    </div>
</AuthorizeView>
@page "/fetchdata"
@attribute [Authorize(Policy = "HasARequiredRole")]
...
[Authorize(Policy = "HasARequiredRole")]
public class WeatherForecastController : ControllerBase

A .net6(rc1) repo.

我会亲自查看基于声明的权限。这样您就可以将应用程序资源分配给声明。然后将声明动态分配给角色或个人。