You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET Core/Blazor:如何实现基于权限(非策略)的授权

Blazor WASM 动态权限授权实现方案

1. 基础定义:权限枚举与授权需求类

先定义权限操作枚举,以及用于传递授权规则的需求类:

// 权限操作枚举
public enum Permission
{
    View,
    Create,
    Edit,
    Delete
}

// 自定义授权需求,携带页面名称和所需权限
public class PagePermissionRequirement : IAuthorizationRequirement
{
    public string PageName { get; }
    public Permission RequiredPermission { get; }

    public PagePermissionRequirement(string pageName, Permission permission)
    {
        PageName = pageName;
        RequiredPermission = permission;
    }
}

2. 实现动态授权处理器

自定义授权处理器,负责校验用户的权限Claim是否匹配需求:

public class PagePermissionHandler : AuthorizationHandler<PagePermissionRequirement>
{
    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, PagePermissionRequirement requirement)
    {
        // 构造需要匹配的Claim值格式:"页面名称 - Allow 权限类型"
        string requiredClaimValue = $"{requirement.PageName} - Allow {requirement.RequiredPermission}";
        
        // 检查用户是否包含对应的Permission类型Claim
        if (context.User.HasClaim(c => c.Type == "Permission" && c.Value == requiredClaimValue))
        {
            context.Succeed(requirement);
        }

        return Task.CompletedTask;
    }
}

3. 创建自定义页面授权特性

替代内置[Authorize]的自定义特性,自动关联动态授权规则:

public class PagePermissionsAttribute : AuthorizeAttribute
{
    public PagePermissionsAttribute(string pageName, Permission permission)
    {
        // 生成唯一策略名称,用于关联动态授权需求
        Policy = $"PagePermission_{pageName}_{permission}";
    }
}

// 动态策略提供器,负责根据策略名称生成对应授权规则
public class DynamicPermissionPolicyProvider : DefaultAuthorizationPolicyProvider
{
    private readonly IOptions<AuthorizationOptions> _options;

    public DynamicPermissionPolicyProvider(IOptions<AuthorizationOptions> options) : base(options)
    {
        _options = options;
    }

    public override async Task<AuthorizationPolicy?> GetPolicyAsync(string policyName)
    {
        // 识别自定义页面权限策略格式
        if (policyName.StartsWith("PagePermission_"))
        {
            var parts = policyName.Split('_');
            if (parts.Length == 3 && Enum.TryParse<Permission>(parts[2], out var permission))
            {
                var policyBuilder = new AuthorizationPolicyBuilder();
                policyBuilder.AddRequirements(new PagePermissionRequirement(parts[1], permission));
                return policyBuilder.Build();
            }
        }

        // 其他策略交给默认提供器处理
        return await base.GetPolicyAsync(policyName);
    }
}

4. 扩展AuthorizeView组件

创建支持传入页面名称和权限的自定义授权组件:

@using Microsoft.AspNetCore.Authorization
@namespace YourAppNamespace.Components

<AuthorizeView Policy="@PolicyName">
    <Authorized>@ChildContent</Authorized>
    <NotAuthorized>@NotAuthorizedContent</NotAuthorized>
    <Authorizing>@AuthorizingContent</Authorizing>
</AuthorizeView>

@code {
    [Parameter] public string PageName { get; set; } = string.Empty;
    [Parameter] public Permission RequiredPermission { get; set; }
    [Parameter] public RenderFragment? ChildContent { get; set; }
    [Parameter] public RenderFragment? NotAuthorizedContent { get; set; }
    [Parameter] public RenderFragment? AuthorizingContent { get; set; }

    private string PolicyName => $"PagePermission_{PageName}_{RequiredPermission}";
}

5. 注册授权服务

在Program.cs中注册自定义授权相关服务:

// 注册授权基础服务
builder.Services.AddAuthorization();

// 注册自定义授权处理器
builder.Services.AddScoped<IAuthorizationHandler, PagePermissionHandler>();

// 替换为动态策略提供器
builder.Services.AddSingleton<IAuthorizationPolicyProvider, DynamicPermissionPolicyProvider>();

6. 认证时注入权限Claims

登录流程中,从数据库获取用户权限并添加到Claims:

// 从数据库/API获取用户权限列表
var userPermissions = await _userPermissionService.GetPermissionsForUserAsync(currentUserId);

// 构建ClaimsIdentity
var identity = new ClaimsIdentity();
foreach (var perm in userPermissions)
{
    // 按照约定格式添加Permission类型Claim
    identity.AddClaim(new Claim("Permission", $"{perm.PageName} - Allow {perm.PermissionType}"));
}

// 更新认证状态
var authState = new AuthenticationState(new ClaimsPrincipal(identity));
await _authenticationStateProvider.SetAuthenticationStateAsync(authState);

使用示例

页面级授权

在Blazor页面顶部添加自定义特性:

@page "/users"
@attribute [PagePermissions("Users", Permission.View)]

<h3>用户管理页面</h3>

组件内局部授权

使用自定义的PageAuthorizeView组件控制局部内容显示:

<PageAuthorizeView PageName="Users" RequiredPermission="Permission.Create">
    <button class="btn btn-primary">创建用户</button>
    <NotAuthorized>
        <p class="text-muted">您没有创建用户的权限</p>
    </NotAuthorized>
</PageAuthorizeView>

内容的提问来源于stack exchange,提问作者Wade Baird

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 10:42:45