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

ASP.NET Core中PermissionCheckerAttribute重定向至NotFound而非登录页问题

未认证时自定义跳转至NotFound页面的解决方法

问题原因

你创建的PermissionCheckerAttribute继承了AuthorizeAttribute,这个基类自带授权逻辑:当检测到用户未认证时,会自动设置跳转至登录页的结果。即便你在IAuthorizationFilter的OnAuthorization方法中指定了跳转到/NotFound,AuthorizeAttribute的后续逻辑会覆盖这个结果,导致最终跳转到登录页。

解决方案

方案一:移除对AuthorizeAttribute的继承,仅实现IAuthorizationFilter

完全抛弃基类的默认逻辑,由自己全权控制授权与跳转行为。同时改用构造函数注入IUserServices,比从RequestServices获取更符合依赖注入规范。

修改后的代码:

public class PermissionCheckerAttribute : IAuthorizationFilter
{
    private readonly IUserServices _userServices;
    private readonly int _permissionId;

    // 构造函数注入依赖
    public PermissionCheckerAttribute(int permissionId, IUserServices userServices)
    {
        _permissionId = permissionId;
        _userServices = userServices;
    }

    public void OnAuthorization(AuthorizationFilterContext context)
    {
        if (context.HttpContext.User.Identity.IsAuthenticated)
        {
            var phoneNumber = context.HttpContext.User.Identity.Name;

            if (!_userServices.CheckPermission(_permissionId, phoneNumber))
            {
                context.Result = new RedirectResult("/NotFound");
            }
        }
        else
        {
            context.Result = new RedirectResult("/NotFound");
        }
    }
}

使用该特性时,因为构造函数需要注入服务,不能直接用[PermissionChecker(1)],需要改用TypeFilterAttribute来包装:

[TypeFilter(typeof(PermissionCheckerAttribute), Arguments = new object[] { 1 })]
public IActionResult SomeAction()
{
    // ...
}

方案二:保留继承AuthorizeAttribute,重写HandleUnauthorizedRequest方法

如果需要保留AuthorizeAttribute的其他特性(比如角色、策略支持),可以重写它处理未授权请求的方法,自定义未认证时的跳转目标。

修改后的代码:

public class PermissionCheckerAttribute : AuthorizeAttribute, IAuthorizationFilter
{
    private IUserServices _userServices;
    private readonly int _permissionId;

    public PermissionCheckerAttribute(int permissionId)
    {
        _permissionId = permissionId;
    }

    public void OnAuthorization(AuthorizationFilterContext context)
    {
        _userServices = (IUserServices)context.HttpContext.RequestServices.GetService(typeof(IUserServices));

        if (context.HttpContext.User.Identity.IsAuthenticated)
        {
            var phoneNumber = context.HttpContext.User.Identity.Name;

            if (!_userServices.CheckPermission(_permissionId, phoneNumber))
            {
                context.Result = new RedirectResult("/NotFound");
            }
        }
        // 未认证的情况交给重写的HandleUnauthorizedRequest处理
    }

    protected override void HandleUnauthorizedRequest(AuthorizationFilterContext context)
    {
        // 替换默认的登录页跳转,改为NotFound页面
        context.Result = new RedirectResult("/NotFound");
    }
}

总结

  • 方案一更灵活,适合完全自定义授权逻辑的场景;
  • 方案二适合需要保留AuthorizeAttribute原有功能的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 14:02:44