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

ASP.NET Core 6 Cookie认证下多授权规则差异化重定向问题

ASP.NET Core 6 Cookie认证差异化授权重定向实现方案

1. 定义自定义授权需求类

创建两个需求类,明确区分角色权限缺失、订阅层级不足两种授权失败场景:

// 角色权限不足需求
public class RoleRequirement : IAuthorizationRequirement
{
    public string RequiredRole { get; set; }
    public RoleRequirement(string role) => RequiredRole = role;
}

// 订阅层级不足需求
public class SubscriptionRequirement : IAuthorizationRequirement
{
    public string RequiredTier { get; set; }
    public SubscriptionRequirement(string tier) => RequiredTier = tier;
}

2. 实现自定义授权处理程序

分别编写处理程序验证用户Claims,验证失败时在授权上下文存储失败类型:

// 角色授权处理程序
public class RoleAuthorizationHandler : AuthorizationHandler<RoleRequirement>
{
    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, RoleRequirement requirement)
    {
        if (context.User.HasClaim(c => c.Type == ClaimTypes.Role && c.Value == requirement.RequiredRole))
        {
            context.Succeed(requirement);
        }
        else
        {
            context.Items["AuthorizationFailureType"] = "RoleMissing";
            context.Fail();
        }
        return Task.CompletedTask;
    }
}

// 订阅授权处理程序
public class SubscriptionAuthorizationHandler : AuthorizationHandler<SubscriptionRequirement>
{
    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, SubscriptionRequirement requirement)
    {
        // 假设订阅层级对应的ClaimType为"SubscriptionTier"
        var userTier = context.User.FindFirstValue("SubscriptionTier");
        if (userTier == requirement.RequiredTier)
        {
            context.Succeed(requirement);
        }
        else
        {
            context.Items["AuthorizationFailureType"] = "SubscriptionMissing";
            context.Fail();
        }
        return Task.CompletedTask;
    }
}

3. 注册授权服务与策略

在Program.cs中注册处理程序,并定义对应授权策略:

builder.Services.AddAuthorization(options =>
{
    // 管理员角色策略
    options.AddPolicy("RequireAdminRole", policy =>
        policy.Requirements.Add(new RoleRequirement("Admin")));

    // 高级版订阅策略
    options.AddPolicy("RequirePremiumSubscription", policy =>
        policy.Requirements.Add(new SubscriptionRequirement("Premium")));
});

// 注册自定义授权处理程序
builder.Services.AddScoped<IAuthorizationHandler, RoleAuthorizationHandler>();
builder.Services.AddScoped<IAuthorizationHandler, SubscriptionAuthorizationHandler>();

4. 配置Cookie认证的差异化重定向事件

重写OnRedirectToAccessDenied事件,根据授权失败类型跳转对应页面:

builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
    .AddCookie(options =>
    {
        options.LoginPath = "/Account/Login"; // 未认证用户跳转登录页
        options.Events.OnRedirectToAccessDenied = context =>
        {
            var authFailFeature = context.HttpContext.Features.Get<IAuthorizationFailureFeature>();
            string failureType = null;

            if (authFailFeature?.Failure != null)
            {
                authFailFeature.Failure.Items.TryGetValue("AuthorizationFailureType", out var obj);
                failureType = obj as string;
            }

            // 根据失败类型分配跳转地址
            string redirectUrl = failureType switch
            {
                "RoleMissing" => "/Account/RoleAccessDenied",
                "SubscriptionMissing" => "/Account/SubscriptionAccessDenied",
                _ => "/Account/AccessDenied" // 默认兜底页面
            };

            context.Response.Redirect(redirectUrl);
            return Task.CompletedTask;
        };
    });

5. 配置UseEndpoints路由

ASP.NET Core 6中需使用UseEndpoints替代UseMvc,确保授权逻辑正常触发:

app.UseRouting();

app.UseAuthentication();
app.UseAuthorization();

app.UseEndpoints(endpoints =>
{
    endpoints.MapControllerRoute(
        name: "default",
        pattern: "{controller=Home}/{action=Index}/{id?}");
    endpoints.MapRazorPages(); // 若使用Razor Pages需添加此配置
});

6. 控制器/页面中使用授权特性

在需要授权的控制器或动作上应用自定义策略:

// 需管理员角色的控制器
[Authorize(Policy = "RequireAdminRole")]
public class AdminController : Controller
{
    // 控制器逻辑
}

// 需高级订阅的动作
[Authorize(Policy = "RequirePremiumSubscription")]
public IActionResult PremiumExclusiveFeature()
{
    return View();
}

补充说明

  • 若需兼容原生[Authorize(Roles = "Admin")]特性,建议统一替换为自定义策略,便于统一控制失败类型;
  • 确保用户Claims中已正确包含Role和SubscriptionTier类型的声明;
  • 保留默认兜底页面,处理未定义的授权失败场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 06:05:17