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
相关产品推荐
相关产品推荐

