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

ASP.NET MVC5迁移.NET 5 Core MVC 实现基于用户Locked属性的控制器授权

ASP.NET MVC5自定义授权迁移至ASP.NET Core 5方案

完全可以实现完全一致的授权逻辑,ASP.NET Core中推荐使用以下两种方案实现:

方案1:自定义IAuthorizationFilter(快速迁移首选)

该方案改造成本极低,用法和原有CustomAuthorizeAttribute完全一致。

步骤1:实现授权过滤器

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Identity;
using YourNamespace.Models; // 替换为你项目中ApplicationUser的实际命名空间

public class CustomAuthorizeFilter : IAuthorizationFilter
{
    private readonly UserManager<ApplicationUser> _userManager;
    private readonly string _roles;
    private readonly string _policy;

    public CustomAuthorizeFilter(UserManager<ApplicationUser> userManager, string roles, string policy)
    {
        _userManager = userManager;
        _roles = roles;
        _policy = policy;
    }

    public void OnAuthorization(AuthorizationFilterContext context)
    {
        // 跳过标注[AllowAnonymous]的接口/控制器
        var hasAllowAnonymous = context.ActionDescriptor.EndpointMetadata
            .Any(m => m is AllowAnonymousAttribute);
        if (hasAllowAnonymous) return;

        var currentUser = context.HttpContext.User;
        // 未登录/用户名为空走默认授权逻辑
        if (currentUser.Identity == null || !currentUser.Identity.IsAuthenticated || string.IsNullOrEmpty(currentUser.Identity.Name))
        {
            context.Result = new ChallengeResult();
            return;
        }

        // 获取当前登录的ApplicationUser实体
        var applicationUser = _userManager.GetUserAsync(currentUser).GetAwaiter().GetResult();
        if (applicationUser == null)
        {
            context.Result = new ChallengeResult();
            return;
        }

        // 用户锁定直接跳转到未授权页
        if (applicationUser.IsLocked)
        {
            context.Result = new RedirectResult("~/home/unauthorized");
            return;
        }

        // 校验角色/策略权限
        var authorizeBuilder = new AuthorizationPolicyBuilder();
        if (!string.IsNullOrEmpty(_roles)) authorizeBuilder.RequireRole(_roles.Split(','));
        if (!string.IsNullOrEmpty(_policy)) authorizeBuilder.RequirePolicy(_policy);
        var policy = authorizeBuilder.Build();
        var authResult = context.HttpContext.AuthenticateAsync().GetAwaiter().GetResult();
        var authorizeResult = new DefaultAuthorizationService(
            new[] { new DefaultAuthorizationHandlerProvider(new IAuthorizationHandler[] { }) },
            new DefaultAuthorizationPolicyProvider(Microsoft.Extensions.Options.Options.Create(new AuthorizationOptions())),
            new DefaultAuthorizationHandlerContextFactory(),
            new DefaultAuthorizationEvaluator(),
            Microsoft.Extensions.Options.Options.Create(new AuthorizationOptions())
        ).AuthorizeAsync(authResult.Principal, context.Resource, policy).GetAwaiter().GetResult();
        
        if (!authorizeResult.Succeeded)
        {
            context.Result = new RedirectResult("~/home/unauthorized");
        }
    }
}

步骤2:实现对应的自定义Attribute

public class CustomAuthorizeAttribute : TypeFilterAttribute
{
    /// <summary>
    /// 允许访问的角色,多个用英文逗号分隔
    /// </summary>
    public string Roles { get; set; }
    /// <summary>
    /// 授权策略名称
    /// </summary>
    public string Policy { get; set; }

    public CustomAuthorizeAttribute() : base(typeof(CustomAuthorizeFilter))
    {
        Arguments = new object[] { Roles, Policy };
    }
}

步骤3:注册服务

在Startup.cs的ConfigureServices方法中添加过滤器注册:

services.AddScoped<CustomAuthorizeFilter>();

使用方式

和原有用法完全一致,直接在控制器或者Action上标注即可:

[CustomAuthorize(Roles = "Admin")]
public class AdminController : Controller
{
    // ...
}

方案2:基于策略的授权(官方推荐,扩展性更强)

符合ASP.NET Core的原生设计规范,适合后续授权逻辑需要扩展的场景。

步骤1:定义授权需求

using Microsoft.AspNetCore.Authorization;

public class ValidUserRequirement : IAuthorizationRequirement
{
}

步骤2:实现需求处理器

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using YourNamespace.Models;

public class ValidUserHandler : AuthorizationHandler<ValidUserRequirement>
{
    private readonly UserManager<ApplicationUser> _userManager;

    public ValidUserHandler(UserManager<ApplicationUser> userManager)
    {
        _userManager = userManager;
    }

    protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, ValidUserRequirement requirement)
    {
        if (context.User.Identity == null || !context.User.Identity.IsAuthenticated)
        {
            context.Fail();
            return;
        }

        var user = await _userManager.GetUserAsync(context.User);
        if (user == null || user.IsLocked)
        {
            context.Fail();
            return;
        }

        context.Succeed(requirement);
    }
}

步骤3:注册授权策略和处理器

在Startup.cs的ConfigureServices方法中添加注册:

services.AddAuthorization(options =>
{
    options.AddPolicy("ValidUser", policy =>
    {
        policy.RequireAuthenticatedUser();
        policy.AddRequirements(new ValidUserRequirement());
        // 可在此添加其他授权要求,如RequireRole("Admin")等
    });
});
services.AddScoped<IAuthorizationHandler, ValidUserHandler>();

// 配置未授权跳转路径
services.ConfigureApplicationCookie(options =>
{
    options.AccessDeniedPath = "/home/unauthorized";
});

使用方式

在需要授权的控制器或Action上标注即可:

[Authorize(Policy = "ValidUser", Roles = "Admin")]
public class AdminController : Controller
{
    // ...
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 15:15:03